115 lines
3.2 KiB
TypeScript
115 lines
3.2 KiB
TypeScript
import path from 'node:path'
|
|
|
|
import { PROJECT_ROOT } from '../../config/runtime.js'
|
|
import { readJsonFile, writeJsonFile } from '../../utils/json-file-store.js'
|
|
|
|
const SCHEDULED_JOBS_FILE_PATH = path.join(PROJECT_ROOT, 'data', 'scheduled-jobs.json')
|
|
const CLOUDTENTACLES_HEALTH_JOB_ID = 'cloudtentacles-health'
|
|
|
|
type JsonObject = Record<string, any>
|
|
|
|
export function getScheduledJobsFilePath() {
|
|
return SCHEDULED_JOBS_FILE_PATH
|
|
}
|
|
|
|
export function getScheduledJobsConfig() {
|
|
return loadScheduledJobsConfigFromFile()
|
|
}
|
|
|
|
export function saveScheduledJobsConfig(rawValue: unknown) {
|
|
return writeJsonFile(SCHEDULED_JOBS_FILE_PATH, rawValue, normalizeScheduledJobsConfig)
|
|
}
|
|
|
|
export function getCloudtentaclesHealthJob(config: JsonObject = getScheduledJobsConfig()) {
|
|
return (Array.isArray(config.jobs) ? config.jobs : [])
|
|
.find((item) => String(item.id || '').trim() === CLOUDTENTACLES_HEALTH_JOB_ID)
|
|
|| createDefaultCloudtentaclesHealthJob()
|
|
}
|
|
|
|
function loadScheduledJobsConfigFromFile() {
|
|
return readJsonFile(
|
|
SCHEDULED_JOBS_FILE_PATH,
|
|
createDefaultScheduledJobsConfig,
|
|
normalizeScheduledJobsConfig,
|
|
)
|
|
}
|
|
|
|
function normalizeScheduledJobsConfig(rawValue: unknown) {
|
|
const source = isPlainObject(rawValue) ? rawValue : {}
|
|
const rawJobs = Array.isArray(source.jobs) ? source.jobs : []
|
|
const jobs = rawJobs.map((item) => normalizeScheduledJob(item)).filter(Boolean)
|
|
const hasCloudtentaclesHealth = jobs.some((item) => item.id === CLOUDTENTACLES_HEALTH_JOB_ID)
|
|
|
|
if (!hasCloudtentaclesHealth) {
|
|
jobs.push(createDefaultCloudtentaclesHealthJob())
|
|
}
|
|
|
|
return {
|
|
enabled: typeof source.enabled === 'boolean' ? source.enabled : true,
|
|
jobs,
|
|
}
|
|
}
|
|
|
|
function normalizeScheduledJob(rawValue: unknown) {
|
|
if (!isPlainObject(rawValue)) {
|
|
return null
|
|
}
|
|
|
|
const type = String(rawValue.type || '').trim()
|
|
if (type !== 'cloudtentacles_health') {
|
|
return null
|
|
}
|
|
|
|
return normalizeCloudtentaclesHealthJob(rawValue)
|
|
}
|
|
|
|
function normalizeCloudtentaclesHealthJob(rawValue: JsonObject) {
|
|
const config = isPlainObject(rawValue.config) ? rawValue.config : {}
|
|
|
|
return {
|
|
id: CLOUDTENTACLES_HEALTH_JOB_ID,
|
|
type: 'cloudtentacles_health',
|
|
enabled: rawValue.enabled === true,
|
|
intervalSeconds: normalizeRangeInteger(rawValue.intervalSeconds, 300, 60, 86400),
|
|
cooldownSeconds: normalizeRangeInteger(rawValue.cooldownSeconds, 1800, 60, 86400),
|
|
config: {
|
|
assetThreshold: normalizeRangeInteger(config.assetThreshold, 500, 0, 999999),
|
|
},
|
|
}
|
|
}
|
|
|
|
function createDefaultScheduledJobsConfig() {
|
|
return {
|
|
enabled: true,
|
|
jobs: [
|
|
createDefaultCloudtentaclesHealthJob(),
|
|
],
|
|
}
|
|
}
|
|
|
|
function createDefaultCloudtentaclesHealthJob() {
|
|
return {
|
|
id: CLOUDTENTACLES_HEALTH_JOB_ID,
|
|
type: 'cloudtentacles_health',
|
|
enabled: false,
|
|
intervalSeconds: 300,
|
|
cooldownSeconds: 1800,
|
|
config: {
|
|
assetThreshold: 500,
|
|
},
|
|
}
|
|
}
|
|
|
|
function normalizeRangeInteger(value: unknown, fallback: number, min: number, max: number) {
|
|
const parsed = Number(value)
|
|
if (!Number.isInteger(parsed)) {
|
|
return fallback
|
|
}
|
|
|
|
return Math.min(max, Math.max(min, parsed))
|
|
}
|
|
|
|
function isPlainObject(value: unknown): value is JsonObject {
|
|
return Object.prototype.toString.call(value) === '[object Object]'
|
|
}
|