57 lines
2.4 KiB
Markdown
57 lines
2.4 KiB
Markdown
# Plan: Backup Scheduling MVP (032)
|
|
|
|
**Date**: 2026-01-05
|
|
**Input**: spec.md
|
|
|
|
## Architecture / Reuse
|
|
- Reuse existing services:
|
|
- `PolicySyncService::syncPoliciesWithReport()` for selected policy types
|
|
- `BackupService::createBackupSet()` to create immutable snapshots + items (include_foundations supported)
|
|
- Store selection as `policy_types` (config keys), not free-form categories.
|
|
- Use tenant scoping (`tenant_id`) consistent with existing tables (`backup_sets`, `backup_items`).
|
|
|
|
## Scheduling Mechanism
|
|
- Add Artisan command: `tenantpilot:schedules:dispatch`.
|
|
- Scheduler integration (Laravel 12): schedule the command every minute via `routes/console.php` + ops configuration (Dokploy cron `schedule:run` or long-running `schedule:work`).
|
|
- Dispatcher algorithm:
|
|
1) load enabled schedules
|
|
2) compute whether due for the current minute in schedule timezone
|
|
3) create run with `scheduled_for` slot (minute precision) using DB unique constraint
|
|
4) dispatch `RunBackupScheduleJob(schedule_id, run_id)`
|
|
- Concurrency:
|
|
- Cache lock per schedule (`lock:backup_schedule:{id}`) plus DB unique slot constraint for idempotency.
|
|
|
|
## Run Execution
|
|
- `RunBackupScheduleJob`:
|
|
1) load schedule + tenant
|
|
2) preflight: tenant active; Graph/auth errors mapped to error_code
|
|
3) sync policies for selected types (collect report)
|
|
4) select policy IDs from local DB for those types (exclude ignored)
|
|
5) create backup set:
|
|
- name: `{schedule_name} - {Y-m-d H:i}`
|
|
- includeFoundations: schedule flag
|
|
6) set run status:
|
|
- success if backup_set.status == completed
|
|
- partial if backup_set.status == partial OR sync had failures but backup succeeded
|
|
- failed if nothing backed up / hard error
|
|
7) update schedule last_run_* and compute/persist next_run_at
|
|
8) dispatch retention job
|
|
|
|
## Retention
|
|
- `ApplyBackupScheduleRetentionJob(schedule_id)`:
|
|
- identify runs ordered newest→oldest
|
|
- keep last N runs that created a backup_set_id
|
|
- for older ones: soft-delete referenced BackupSets (and cascade soft-delete items)
|
|
|
|
## Filament UX
|
|
- Tenant-scoped resources:
|
|
- `BackupScheduleResource`
|
|
- Runs UI via RelationManager under schedule (or a dedicated resource if needed)
|
|
- Actions: enable/disable, run now, retry
|
|
- Notifications: persist via `->sendToDatabase($user)` for the DB info panel.
|
|
|
|
## Ops / Deployment Notes
|
|
- Requires queue worker.
|
|
- Requires scheduler running.
|
|
- Missed runs policy (MVP): no catch-up.
|