2.4 KiB
2.4 KiB
After refinement-phase-7 — Unattended operation (scheduler, locking, migrations-from-boot)
For the frontend / next backend phase. Backend-owned; frontend reads.
What changed for a client
Almost nothing user-facing — this is infrastructure. One wire delta:
PayoutBatchDto.initiatedByAdminIdis now nullable.null= a system-initiated / scheduled payout batch (the weekly cron generated it, no human initiator). Admin payout UIs should render a "system"/"scheduled" label instead of assuming an admin id. Contract +swagger.v1.jsonupdated.
What the platform now does on its own
The four previously admin-click-only sweeps run on schedule (each reading its platform_configs cadence key):
credential-expiry scan, EVV no-show sweep, and weekly payout-batch generation — plus the two re-homed sweeps
(booking-request expiry, notification retention). Admin manual triggers are unchanged and remain overrides.
- Payout generation only. The cron opens a
draftbatch; processing (money movement) is still an explicit admin action (POST admin_payouts/batches/{id}/process). Do not build a client flow that auto-processes.
For the next backend phase (Phase 8 — external rails)
- Register new crons via the seam, not a new host. Implement
IRecurringJob(Persistence/Services/Scheduling/) + oneservices.AddSingleton<IRecurringJob, YourJob>()inAddPersistenceServices. Phase 8 owns the Moadian reconciliation poll and the refund-settlement reconciliation this way (each reads/adds its own cadence key). The scheduler already provides the per-tick scope, thescheduler:{name}lock, and error isolation. - Jobs must stay idempotent — a retry (or a second instance once the lock is Redis-backed) must never double-pay/double-post; the DB uniques/state-machines are the backstop.
Ops / deployment
- DDL is a deploy step now: run
dotnet run -- migrate(applies migrations + idempotent seeders, then exits) before starting the API in a deployed environment. A normal deployed boot only checks the schema and fails fast if a migration is pending. Development still migrates + seeds on boot. - Redis is the >1-instance gate (shared cache + the cross-instance scheduler/money lock). Single-instance MVP does not need it; the in-proc seams are correct for one instance. Elasticsearch is never MVP.