Skip to content

Daily flag-sync cron

DailyFlagSyncWorkflow (src/workflows/daily-flag-sync.ts) runs once daily at 06:00Z (midnight MT). It’s the cold-start mechanism — if a booking exists in Beds24 but has no BookingFlagWorkflow instance, this cron spawns one.

What it does

  1. Read feature flag — skips if daily-flag-sync.enabled=0
  2. Fetch bookings via Beds24 v2 API:
    • Default horizon: 365 days forward
    • Filter: status IN (confirmed, new, request)
  3. For each booking: call ensureBookingFlagWorkflow(env, b.id, { force: false }) — spawns a new workflow only if none exists OR the existing one is errored/terminated. Healthy workflows (queued / running / paused / waiting / complete) are left alone so the cron doesn’t tear down + recreate every active booking every morning.

Why we still need it

Most new bookings arrive via the Beds24 booking-event push webhook, which spawns the workflow immediately. The cron is the safety net for:

  • Push webhook misconfiguration — if the BA panel push setting gets disabled, this cron picks up new bookings within 24h
  • Stale workflows — if a workflow instance was terminated without a respawn
  • Recovery after outages — after a service blip, the cron re-establishes correct state next morning

Idempotency

ensureBookingFlagWorkflow terminates + respawns when force=true (webhook + admin callers). All workflow phases handle respawn cleanly via D1 / infoItem state checks before acting. With force=false (this cron’s setting), healthy workflows are skipped so daily-sync only does work when a workflow is actually missing or broken.

Manual one-shot

POST /admin/backfill

Spawns the same workflow with triggeredBy=backfill, horizonDays=365. Useful after schema changes or to force a full re-sync.

Shadow mode

daily-flag-sync.shadow_mode has been 0 (real) since Phase 2 went live. Flipping to 1 causes the cron to write predictions but skip the workflow spawns — emergency brake.