fix(quick-260610-i4x-01): replace node-cron schedule() with setInterval in three broker workers
- poller.ts: setInterval(cb, 5 * 60 * 1000) replaces schedule('*/5 * * * *', cb)
- outboxWorker.ts: setInterval(cb, 15 * 1000) replaces schedule('*/15 * * * * *', cb)
- reminderScheduler.ts: setInterval(cb, 60 * 1000) replaces schedule('* * * * *', cb)
- Remove 'import { schedule } from node-cron' from all three files
- Update doc comments to reflect setInterval and document why (node-cron 4.2.1 silent skip)
- Callback bodies and .catch wrappers unchanged; typecheck clean; 91/91 broker tests pass
This commit is contained in:
@@ -17,13 +17,12 @@
|
|||||||
* T-03-14: create-before-delete ordering; create-fail aborts delete.
|
* T-03-14: create-before-delete ordering; create-fail aborts delete.
|
||||||
*
|
*
|
||||||
* runOutboxDrain is exported for unit testing.
|
* runOutboxDrain is exported for unit testing.
|
||||||
* startOutboxWorker wraps it in a 15-second node-cron schedule.
|
* startOutboxWorker wraps it in a 15-second setInterval.
|
||||||
|
* (node-cron 4.2.1 silently skipped scheduled executions in the long-running server process;
|
||||||
|
* setInterval fires reliably in the same process — replaced to fix the silent skip.)
|
||||||
*
|
*
|
||||||
* Source: poller.ts pattern (runPoll/startBrokerPoller)
|
* Source: poller.ts pattern (runPoll/startBrokerPoller)
|
||||||
* Source: https://github.com/node-cron/node-cron (v4 stable)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { schedule } from 'node-cron'
|
|
||||||
import { z } from 'zod'
|
import { z } from 'zod'
|
||||||
import { and, eq, lte } from 'drizzle-orm'
|
import { and, eq, lte } from 'drizzle-orm'
|
||||||
import { db } from '../db/client.js'
|
import { db } from '../db/client.js'
|
||||||
@@ -752,11 +751,13 @@ export async function runOutboxDrain(): Promise<void> {
|
|||||||
/**
|
/**
|
||||||
* Starts the 15-second background outbox drain schedule.
|
* Starts the 15-second background outbox drain schedule.
|
||||||
* Call once at API startup (wired in index.ts beside startBrokerPoller).
|
* Call once at API startup (wired in index.ts beside startBrokerPoller).
|
||||||
|
* Uses setInterval instead of node-cron: node-cron 4.2.1 silently skipped executions
|
||||||
|
* in the long-running server process; setInterval fires reliably.
|
||||||
*/
|
*/
|
||||||
export function startOutboxWorker(): void {
|
export function startOutboxWorker(): void {
|
||||||
schedule('*/15 * * * * *', () => {
|
setInterval(() => {
|
||||||
runOutboxDrain().catch((err: unknown) => {
|
runOutboxDrain().catch((err: unknown) => {
|
||||||
console.error('[outboxWorker] Unhandled runOutboxDrain error:', err)
|
console.error('[outboxWorker] Unhandled runOutboxDrain error:', err)
|
||||||
})
|
})
|
||||||
})
|
}, 15 * 1000)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* CalDAV broker poller — runs every 5 minutes via node-cron.
|
* CalDAV broker poller — runs every 5 minutes via setInterval.
|
||||||
*
|
*
|
||||||
* Responsibilities (D-13, D-02):
|
* Responsibilities (D-13, D-02):
|
||||||
* - Load all member_credentials (N-credential per-member model)
|
* - Load all member_credentials (N-credential per-member model)
|
||||||
@@ -10,12 +10,10 @@
|
|||||||
* → ctag changed or null: call syncCalendar (REPORT → ical.js → DB upsert)
|
* → ctag changed or null: call syncCalendar (REPORT → ical.js → DB upsert)
|
||||||
*
|
*
|
||||||
* runPoll is exported for unit testing (inject mocks via vi.mock at the module level).
|
* runPoll is exported for unit testing (inject mocks via vi.mock at the module level).
|
||||||
* startBrokerPoller wraps it in node-cron's 5-minute schedule.
|
* startBrokerPoller wraps it in a 5-minute setInterval.
|
||||||
*
|
* (node-cron 4.2.1 silently skipped scheduled executions in the long-running server process;
|
||||||
* Source: https://github.com/node-cron/node-cron (v4 stable basic API)
|
* setInterval fires reliably in the same process — replaced to fix the silent skip.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { schedule } from 'node-cron'
|
|
||||||
import { and, eq } from 'drizzle-orm'
|
import { and, eq } from 'drizzle-orm'
|
||||||
import { db } from '../db/client.js'
|
import { db } from '../db/client.js'
|
||||||
import { memberCredentials, calendars } from '../db/schema.js'
|
import { memberCredentials, calendars } from '../db/schema.js'
|
||||||
@@ -91,11 +89,13 @@ export async function runPoll(): Promise<void> {
|
|||||||
/**
|
/**
|
||||||
* Starts the 5-minute background polling schedule.
|
* Starts the 5-minute background polling schedule.
|
||||||
* Call once at API startup (Plan 04 wires this into index.ts).
|
* Call once at API startup (Plan 04 wires this into index.ts).
|
||||||
|
* Uses setInterval instead of node-cron: node-cron 4.2.1 silently skipped executions
|
||||||
|
* in the long-running server process; setInterval fires reliably.
|
||||||
*/
|
*/
|
||||||
export function startBrokerPoller(): void {
|
export function startBrokerPoller(): void {
|
||||||
schedule('*/5 * * * *', () => {
|
setInterval(() => {
|
||||||
runPoll().catch((err: unknown) => {
|
runPoll().catch((err: unknown) => {
|
||||||
console.error('[broker/poller] Unhandled runPoll error:', err)
|
console.error('[broker/poller] Unhandled runPoll error:', err)
|
||||||
})
|
})
|
||||||
})
|
}, 5 * 60 * 1000)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* Reminder scheduler — shared-timed-event 15-min reminder scan.
|
* Reminder scheduler — shared-timed-event 15-min reminder scan.
|
||||||
*
|
*
|
||||||
* Fires every minute via node-cron. Each tick calls runReminderCheck() which:
|
* Fires every minute via setInterval. Each tick calls runReminderCheck() which:
|
||||||
|
* (node-cron 4.2.1 silently skipped scheduled executions in the long-running server
|
||||||
|
* process; setInterval fires reliably in the same process — replaced to fix the silent skip.)
|
||||||
* 1. Queries shared (isShared=true) timed (allDay=false) events whose dtstartUtc
|
* 1. Queries shared (isShared=true) timed (allDay=false) events whose dtstartUtc
|
||||||
* falls in (now, now+16min] — strictly after now (future only; excludes
|
* falls in (now, now+16min] — strictly after now (future only; excludes
|
||||||
* already-started events) and at most 16 min out. Because the lower bound
|
* already-started events) and at most 16 min out. Because the lower bound
|
||||||
@@ -31,7 +33,6 @@
|
|||||||
* T-05-19 — per-subscription try/catch; dispatchPush already swallows 410/404.
|
* T-05-19 — per-subscription try/catch; dispatchPush already swallows 410/404.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { schedule } from 'node-cron'
|
|
||||||
import { and, eq, gt, lte, sql } from 'drizzle-orm'
|
import { and, eq, gt, lte, sql } from 'drizzle-orm'
|
||||||
import { db } from '../db/client.js'
|
import { db } from '../db/client.js'
|
||||||
import { calendars, calendarEvents, pushSubscriptions } from '../db/schema.js'
|
import { calendars, calendarEvents, pushSubscriptions } from '../db/schema.js'
|
||||||
@@ -201,12 +202,14 @@ export async function runReminderCheck(now = new Date()): Promise<void> {
|
|||||||
/**
|
/**
|
||||||
* Start the 1-minute reminder scan schedule.
|
* Start the 1-minute reminder scan schedule.
|
||||||
* Call once from index.ts's isMainModule() guard — NOT at import time
|
* Call once from index.ts's isMainModule() guard — NOT at import time
|
||||||
* (keeps the cron out of the test process; mirrors startBrokerPoller pattern).
|
* (keeps the setInterval out of the test process; mirrors startBrokerPoller pattern).
|
||||||
|
* Uses setInterval instead of node-cron: node-cron 4.2.1 silently skipped executions
|
||||||
|
* in the long-running server process; setInterval fires reliably.
|
||||||
*/
|
*/
|
||||||
export function startReminderScheduler(): void {
|
export function startReminderScheduler(): void {
|
||||||
schedule('* * * * *', () => {
|
setInterval(() => {
|
||||||
runReminderCheck().catch((err: unknown) => {
|
runReminderCheck().catch((err: unknown) => {
|
||||||
console.error('[broker/reminderScheduler] Unhandled runReminderCheck error:', err)
|
console.error('[broker/reminderScheduler] Unhandled runReminderCheck error:', err)
|
||||||
})
|
})
|
||||||
})
|
}, 60 * 1000)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user