wulf-pulse/.planning/quick/260721-fy8-fix-mimecast-and-qbo-sync-scheduler-disp/260721-fy8-SUMMARY.md
2026-07-21 11:39:52 -04:00

4.1 KiB

phase plan subsystem tags key-decisions status
quick-260721-fy8 01 sync-scheduler
scheduler
mimecast
qbo
migration
bugfix
mimecast-sync and qbo dispatch branches use incrementalSync (not fullSync) — matches the manual /api/qbo/sync non-full path and is correct for a twice-daily recurring job
Chose 45 4 * * * for mimecast-sync's new cron slot — minute 45 is unused anywhere in the live sync_schedules table, avoiding 0 4 (contract-services, pax8-daily), 30 4 (tickets-reconcile), the hourly :15 device-link job, and the veeam */30 :00/:30 jobs
Migration 101 guards the UPDATE on the stale '0 2 * * *' value so it's a no-op if already moved and won't clobber an admin's manual schedule change made via /admin after this ships
complete

Quick Task 260721-fy8: Fix mimecast and qbo sync scheduler dispatch and reschedule mimecast cron

One-liner: Added missing mimecast-sync and qbo dispatch branches to sync-scheduler.ts (both previously fell through to a generic Autotask full sync, silently never running their real sync logic) and rescheduled mimecast-sync off the 2am three-way cron collision with qbo-sync-2am and veeam-full.

What was done

Task 1 — Dispatch branches (lib/services/sync-scheduler.ts, commit 9311f10)

  • Extended the ScheduleConfig.sync_type union to add 'mimecast-sync' ('qbo' was already present).
  • Added an else if (config.sync_type === 'mimecast-sync') branch: dynamically imports isMimecastConfigured from mimecast-client.ts; if not configured, logs a skip line matching the engagement/zoom wording. Otherwise dynamically imports and calls runMimecastIncrementalSync() from mimecast-sync-service.ts, logging a one-line summary using the real MimecastSyncResult fields (messagesUpserted, threatsUpserted, bodiesFetched, purgedMessages, errors.length, durationMs).
  • Added an else if (config.sync_type === 'qbo') branch: queries integration_settings for key = 'qbo' (mirroring the pax8-daily disable-check pattern exactly); if disabled, logs a skip line; otherwise dynamically imports getQboSyncService and calls .incrementalSync('scheduled').
  • Both new branches sit before the final 'incremental' branch and catch-all else, which are unchanged — the catch-all remains reachable only for 'full'/legacy full-sync types.
  • npx tsc --noEmit --pretty passes clean.

Task 2 — Reschedule migration (migrations/101_reschedule_mimecast_sync.sql, commit f447ac3)

  • New guarded migration: UPDATE sync_schedules SET cron_expression = '45 4 * * *', updated_at = NOW() WHERE id = 'mimecast-sync' AND cron_expression = '0 2 * * *' — a no-op if already moved, safe against clobbering a manual admin change.
  • Applied the same UPDATE directly against the live pulse-postgres container (migrations only auto-apply on first volume boot per CLAUDE.md) — confirmed live: mimecast-sync now reads 45 4 * * *; qbo-sync-2am and veeam-full unchanged at 0 2 * * * (collision eliminated for mimecast-sync specifically, as intended — qbo-sync-2am and veeam-full no longer contend with mimecast-sync, though qbo-sync-2am and veeam-full still share 2am with each other, which was out of scope for this task).

Verification

  • npx tsc --noEmit --pretty — clean.
  • Live DB: SELECT cron_expression FROM sync_schedules WHERE id = 'mimecast-sync'45 4 * * *.
  • No existing branch (phishing-sweep, pax8-daily, veeam-*, incremental, catch-all) modified.
  • No test file exists for sync-scheduler.ts (only mimecast-client.test.ts), so no test changes were made, per plan constraint.

Deviations from plan

None. Both tasks executed exactly as planned.

Note on this SUMMARY.md

This file was originally written by the executor inside its isolated git worktree but was lost when the orchestrator removed the worktree (git worktree remove --force) without first running the standard rescue-before-remove step. Reconstructed immediately after from the executor's final report text and the actual git show output of both commits — content is accurate but not verbatim the original (same recovery situation documented previously in this repo for quick task 260717-a19).