mirror of
https://github.com/hansjone/dsh-ops-cron.git
synced 2026-10-09 01:53:19 +08:00
Recover from corrupt ops-cron store and tighten cron tool schemas.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
b1bb0067a0
commit
25454a5c8c
4 changed files with 58 additions and 6 deletions
39
lib/store.js
39
lib/store.js
|
|
@ -216,11 +216,46 @@ export function createStore(options = {}) {
|
|||
async function load() {
|
||||
try {
|
||||
const raw = await readFile(filePath, 'utf8')
|
||||
// Reject embedded NUL — JSON.parse would throw an opaque "Unexpected token".
|
||||
if (raw.includes('\u0000')) {
|
||||
const error = new Error(`ops-cron store is corrupt (NUL byte) at ${filePath}; moved aside and starting empty`)
|
||||
error.code = 'STORE_CORRUPT'
|
||||
try {
|
||||
const bak = `${filePath}.corrupt.${Date.now()}.bak`
|
||||
await writeFile(bak, raw, 'utf8')
|
||||
error.message = `${error.message} (backup: ${bak})`
|
||||
} catch {
|
||||
// best-effort backup
|
||||
}
|
||||
console.warn(`[dsh-ops-cron] ${error.message}`)
|
||||
state = emptyState()
|
||||
loaded = true
|
||||
await persist()
|
||||
return snapshot()
|
||||
}
|
||||
const parsed = JSON.parse(raw)
|
||||
state = hydrate(parsed)
|
||||
} catch (error) {
|
||||
if (error && error.code === 'ENOENT') state = emptyState()
|
||||
else throw error
|
||||
if (error && error.code === 'ENOENT') {
|
||||
state = emptyState()
|
||||
} else if (error instanceof SyntaxError) {
|
||||
const wrapped = new Error(`ops-cron store JSON parse failed at ${filePath}: ${error.message}`)
|
||||
wrapped.code = 'STORE_CORRUPT'
|
||||
wrapped.cause = error
|
||||
try {
|
||||
const raw = await readFile(filePath, 'utf8').catch(() => '')
|
||||
if (raw) await writeFile(`${filePath}.corrupt.${Date.now()}.bak`, raw, 'utf8')
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
console.warn(`[dsh-ops-cron] ${wrapped.message}; starting empty store`)
|
||||
state = emptyState()
|
||||
loaded = true
|
||||
await persist()
|
||||
return snapshot()
|
||||
} else {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
loaded = true
|
||||
return snapshot()
|
||||
|
|
|
|||
|
|
@ -41,9 +41,9 @@ const JOB_SCHEMA = {
|
|||
schedule: { type: 'object', additionalProperties: true },
|
||||
createdAt: { type: 'number' },
|
||||
updatedAt: { type: 'number' },
|
||||
lastRunAt: {},
|
||||
lastStatus: {},
|
||||
nextRunAt: {},
|
||||
lastRunAt: { type: ['number', 'null'] },
|
||||
lastStatus: { type: ['string', 'null'] },
|
||||
nextRunAt: { type: ['number', 'null'] },
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue