56 lines
2.8 KiB
Go
56 lines
2.8 KiB
Go
package maintenance
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
// OrphanedMediaRetentionStore deletes documents/photos that have been
|
|
// orphaned (no live message/profile-photo/sticker-set reference remains,
|
|
// tracked via media_references + orphaned_at) for at least the configured
|
|
// age, along with their underlying blob once no other file_blobs row on
|
|
// its backend still needs it. Never touches media that still has a live
|
|
// reference, regardless of age.
|
|
type OrphanedMediaRetentionStore interface {
|
|
DeleteOrphanedOlderThan(ctx context.Context, cutoff time.Time, limit int) (int, error)
|
|
}
|
|
|
|
// WithOrphanedMediaRetention enables the storage retention sweep. maxAge is
|
|
// how long a document/photo must have been orphaned before it's actually
|
|
// deleted (not how old the media itself is) -- <=0 leaves the sweep
|
|
// disabled even if a store is provided, matching
|
|
// TELESRV_STORAGE_RETENTION_MODE=off/orphan-with-no-age being the safe
|
|
// default. Mutually exclusive with WithHardMediaRetention -- the resolved
|
|
// TELESRV_STORAGE_RETENTION_MODE is one of "off"/"orphan"/"hard", never
|
|
// both orphan and hard sweeps at once.
|
|
func (w *RetentionWorker) WithOrphanedMediaRetention(store OrphanedMediaRetentionStore, maxAge time.Duration) *RetentionWorker {
|
|
w.orphanedMedia = store
|
|
w.orphanedMediaMaxAge = maxAge
|
|
return w
|
|
}
|
|
|
|
// HardMediaRetentionStore physically deletes a document/photo's blob bytes
|
|
// once the media itself (its upload/created time, not how long it has been
|
|
// orphaned) is older than the configured age, REGARDLESS of whether a live
|
|
// message/profile-photo/sticker-set still references it. Unlike
|
|
// OrphanedMediaRetentionStore, it must never delete the document/photo
|
|
// metadata row -- only the underlying file_blobs row(s) and, once confirming
|
|
// no other row still needs the same content-addressed object, the physical
|
|
// bytes. This keeps a message rendering its media placeholder (dimensions,
|
|
// mime type, filename) after the bytes are gone; a subsequent download
|
|
// resolves to LOCATION_INVALID instead of the message breaking outright.
|
|
type HardMediaRetentionStore interface {
|
|
DeleteBlobBytesForMediaOlderThan(ctx context.Context, cutoff time.Time, limit int) (int, error)
|
|
}
|
|
|
|
// WithHardMediaRetention enables the aggressive storage retention sweep
|
|
// (TELESRV_STORAGE_RETENTION_MODE=hard). maxAge is how old the media itself
|
|
// must be (its created_at, not an orphaned_at grace period) before its blob
|
|
// bytes are purged -- <=0 leaves the sweep disabled even if a store is
|
|
// provided. Mutually exclusive with WithOrphanedMediaRetention -- call at
|
|
// most one of the two, matching the config's single 3-way retention mode.
|
|
func (w *RetentionWorker) WithHardMediaRetention(store HardMediaRetentionStore, maxAge time.Duration) *RetentionWorker {
|
|
w.hardMedia = store
|
|
w.hardMediaMaxAge = maxAge
|
|
return w
|
|
}
|