backend: GDPR export + retention cleanups + worker metrics (BE-1/2/3)
BE-3 observability: expose the worker's Prometheus metrics on :6060/metrics (apns/fcm/asynq histograms + a new cache_ops_total counter were recorded all along but never scraped — which is why those dashboard panels read empty); add the worker containerPort, the vmagent worker scrape job, and two additive NetworkPolicies. Instrument cache Get/Set hit/miss. BE-2 retention: three periodic Asynq cleanup crons mirroring the reminder-log cleanup — notifications (90d), webhook dedup log (180d), audit_log (365d). BE-1 GDPR data export: POST /api/auth/export/ enqueues a low-priority Asynq job that gathers all of the user's data (owned residences + their tasks/contractors/ documents/share-codes, plus profile/notifications/prefs/push-tokens/subscription/ audit log), zips one JSON file per category, and emails it as an attachment. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,8 +21,17 @@ const (
|
||||
// Moves the ~1-1.5s of synchronous APNs+SMTP+B2-fetch work out of the
|
||||
// POST /api/task-completions/ request path.
|
||||
TypeTaskCompletedNotification = "notification:task_completed"
|
||||
|
||||
// TypeDataExport is emitted by POST /api/auth/export/. The worker gathers
|
||||
// all of the user's data into a zip and emails it (GDPR data portability).
|
||||
TypeDataExport = "user:data_export"
|
||||
)
|
||||
|
||||
// DataExportPayload carries just the user id; the worker re-fetches all rows.
|
||||
type DataExportPayload struct {
|
||||
UserID uint `json:"user_id"`
|
||||
}
|
||||
|
||||
// TaskCompletedNotificationPayload carries only the IDs needed for the
|
||||
// worker to re-fetch the canonical Task + TaskCompletion rows. Keeping the
|
||||
// payload to IDs (vs. full model graphs) keeps the Redis queue cheap and
|
||||
@@ -93,6 +102,26 @@ func (c *TaskClient) EnqueueWelcomeEmail(to, firstName, code string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnqueueDataExport enqueues a GDPR data-export task for a user. The worker
|
||||
// gathers the user's data, zips it, and emails it. Low priority — there's no
|
||||
// rush, and it shouldn't compete with notifications for the critical queue.
|
||||
func (c *TaskClient) EnqueueDataExport(userID uint) error {
|
||||
payload, err := BuildDataExportPayload(userID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
task := asynq.NewTask(TypeDataExport, payload)
|
||||
_, err = c.client.Enqueue(task, asynq.Queue("low"), asynq.MaxRetry(3))
|
||||
if err != nil {
|
||||
log.Error().Err(err).Uint("user_id", userID).Msg("Failed to enqueue data export")
|
||||
return err
|
||||
}
|
||||
|
||||
log.Info().Uint("user_id", userID).Msg("Data export task enqueued")
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnqueueVerificationEmail enqueues a verification email task
|
||||
func (c *TaskClient) EnqueueVerificationEmail(to, firstName, code string) error {
|
||||
payload, err := BuildVerificationEmailPayload(to, firstName, code)
|
||||
|
||||
Reference in New Issue
Block a user