3.5 KiB
3.5 KiB
File Lifecycle and S3 Cleanup
Lifecycle States (DB source of truth)
file_files.lifecycle_status:
temp: uploaded but not attachedactive: referenced by one or more business entitiesorphan_pending: currently unreferenced, waiting grace perioddeleted: backend cleanup has deleted object(s) and marked terminal state
Supporting timestamps:
created_at: existing file creation timeattached_at: set when file becomes activeorphaned_at: set when file becomes unreferencedlifecycle_deleted_at: set when cleanup marks lifecycledeleted
Notes:
- Existing
statuscolumn (uploaded/processing/validated/ready/trashed) remains for processing/trash flow. deleted_atis still used by trash semantics. Cleanup lifecycle useslifecycle_deleted_at.
S3 Tags
Single tag key: gc
gc=temp: temporary uploadsgc=keep: active or protected filesgc=delete: optional marker immediately before backend delete
S3 tags are markers only. DB lifecycle state and DB reference checks are authoritative.
Cleanup Job
Scheduler: API process loop (startFileManagerLifecycleCleanupLoop).
Behavior:
- Query DB for
orphan_pendingfiles whereorphaned_at <= now - ORPHAN_GRACE_PERIOD_DAYS. - Process in batches (
FILE_CLEANUP_BATCH_SIZE). - Re-check DB references per file before deletion.
- If referenced again: mark
active, set/keepgc=keep. - If still unreferenced:
- optional
gc=deletetag - delete original and thumbnail S3 objects
- mark lifecycle
deletedand setlifecycle_deleted_at
- optional
- Per-file error handling; one failure does not stop the batch.
The job is idempotent and retry-safe.
Environment Variables
ENABLE_S3_TAGGING(defaulttrue)ENABLE_FILE_CLEANUP_JOB(defaultfalse)TEMP_FILE_TTL_DAYS(default7)ORPHAN_GRACE_PERIOD_DAYS(default30)FILE_CLEANUP_BATCH_SIZE(default100)FILE_CLEANUP_DRY_RUN(defaulttrue)
Backfill (Dry-Run First)
Command:
go run ./cmd/file-lifecycle-backfill
Optional:
BACKFILL_DRY_RUN=true|false(defaulttrue)
Output report includes:
- active files
- probable orphan files
- missing S3 key
- invalid references
- skipped records
Required IAM Permissions
Minimum required:
s3:PutObjectTaggings3:GetObjectTaggings3:DeleteObjects3:GetObjects3:HeadObject
Only if infra automation updates lifecycle rules:
s3:PutLifecycleConfiguration
S3 Lifecycle Rules (Manual if no IaC)
Because this repository does not define Terraform/CDK/CloudFormation for S3 bucket lifecycle, configure lifecycle rules in your infra/deployment stack:
-
Rule
gc=temp:- Filter: object tag
gc=temp - Expire after
TEMP_FILE_TTL_DAYS(recommended default 7 days)
- Filter: object tag
-
Optional rule
gc=delete:- Filter: object tag
gc=delete - Expire after 1 day
- Filter: object tag
Do not use lifecycle expiration as the orphan grace mechanism. Grace period is enforced by DB orphaned_at.
Rollout Plan
- Deploy schema + code with defaults (
cleanup job off,dry-run on). - Enable tagging for new uploads (
ENABLE_S3_TAGGING=true). - Validate attach/detach transitions in logs.
- Run backfill dry-run and review report.
- Enable cleanup job in dry-run mode.
- Switch cleanup dry-run off after validation.
- Apply S3 lifecycle rules for
gc=temp(and optionalgc=delete).
Rollback Plan
- Set
ENABLE_FILE_CLEANUP_JOB=false. - Set
FILE_CLEANUP_DRY_RUN=true. - Optionally set
ENABLE_S3_TAGGING=false. - Pause/remove lifecycle rule
gc=deleteif enabled.