feat(workload): write-through workload sync + boot-time backfill

CRUD on Project / Stack / StaticSite now keeps a paired Workload
row in sync. Secret setters (webhook secret, signing secret,
require-signature toggle, notification secret) all re-sync after
mutating the source-of-truth row so the workload row always
reflects the canonical state.

Delete cascades: DeleteProject/Stack/StaticSite now drop the
matching workload row plus any container index entries owned by
it, so global views don't show ghost rows.

Boot-time BackfillWorkloads scans every project/stack/site and
ensures each has a workload row. Idempotent — safe to run on
every restart, recovers from a deleted/missing workload row.

Behavior unchanged for existing call sites; the workloads table
just starts being populated. Deployer / reconciler / consumer
switchover land in the next commit.
This commit is contained in:
2026-05-09 13:28:20 +03:00
parent f54a6ecee3
commit db235c1412
7 changed files with 410 additions and 18 deletions
+2 -8
View File
@@ -41,7 +41,7 @@ func (s *Store) CreateWorkload(w Workload) (Workload, error) {
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
w.ID, w.Kind, w.RefID, w.Name, w.AppID,
w.NotificationURL, w.NotificationSecret,
w.WebhookSecret, w.WebhookSigningSecret, boolToInt(w.WebhookRequireSignature),
w.WebhookSecret, w.WebhookSigningSecret, BoolToInt(w.WebhookRequireSignature),
w.CreatedAt, w.UpdatedAt,
)
if err != nil {
@@ -142,7 +142,7 @@ func (s *Store) UpdateWorkload(w Workload) error {
WHERE id=?`,
w.Name, w.AppID,
w.NotificationURL, w.NotificationSecret,
w.WebhookSecret, w.WebhookSigningSecret, boolToInt(w.WebhookRequireSignature),
w.WebhookSecret, w.WebhookSigningSecret, BoolToInt(w.WebhookRequireSignature),
w.UpdatedAt, w.ID,
)
if err != nil {
@@ -184,9 +184,3 @@ func (s *Store) DeleteWorkloadByRef(kind WorkloadKind, refID string) error {
return nil
}
func boolToInt(b bool) int {
if b {
return 1
}
return 0
}