fix
This commit is contained in:
parent
fe1cf1184f
commit
e6a777983c
10 changed files with 174 additions and 2 deletions
|
|
@ -249,6 +249,47 @@ func (s *Service) AdminAutoCategorizeGifCatalog(ctx context.Context) (int, error
|
|||
return changed, nil
|
||||
}
|
||||
|
||||
// AdminDeleteUncategorizedGifs removes every gif_catalog entry with no
|
||||
// category (Category == "") -- both the catalog row and, when safe, the
|
||||
// underlying document/blob. "Safe" means deleteDocumentNowIfUnreferenced
|
||||
// found nothing else pointing at that document (see its doc comment): a
|
||||
// user who already saved or forwarded one of these GIFs before this ran
|
||||
// keeps their copy, only the catalog listing (and the document, if no
|
||||
// longer referenced anywhere) goes away. Returns how many catalog entries
|
||||
// and how many documents were actually deleted.
|
||||
func (s *Service) AdminDeleteUncategorizedGifs(ctx context.Context) (deletedEntries, deletedDocuments int, err error) {
|
||||
if s.gifCatalog == nil {
|
||||
return 0, 0, domain.ErrGifCatalogUnavailable
|
||||
}
|
||||
entries, err := s.gifCatalog.ListGifCatalog(ctx, false, 0)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
for _, e := range entries {
|
||||
if e.Category != "" {
|
||||
continue
|
||||
}
|
||||
ok, err := s.gifCatalog.DeleteGifCatalogEntry(ctx, e.ID)
|
||||
if err != nil {
|
||||
return deletedEntries, deletedDocuments, err
|
||||
}
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
deletedEntries++
|
||||
deleted, err := s.deleteDocumentNowIfUnreferenced(ctx, e.DocumentID)
|
||||
if err != nil {
|
||||
s.log.Warn("delete uncategorized gif document failed",
|
||||
zap.Int64("catalog_entry_id", e.ID), zap.Int64("document_id", e.DocumentID), zap.Error(err))
|
||||
continue
|
||||
}
|
||||
if deleted {
|
||||
deletedDocuments++
|
||||
}
|
||||
}
|
||||
return deletedEntries, deletedDocuments, nil
|
||||
}
|
||||
|
||||
// AdminDeleteGifCatalogEntry removes an entry from the catalog. The
|
||||
// referenced document is left alone.
|
||||
func (s *Service) AdminDeleteGifCatalogEntry(ctx context.Context, id int64) (bool, error) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ type mediaRetentionStore interface {
|
|||
CountFileBlobRefs(ctx context.Context, backend, objectKey string) (int, error)
|
||||
DeleteDocumentAndBlobs(ctx context.Context, id int64) ([]domain.FileBlob, error)
|
||||
DeletePhotoAndBlobs(ctx context.Context, id int64) ([]domain.FileBlob, error)
|
||||
// OrphanDocumentIfUnreferenced is the immediate (no grace period)
|
||||
// counterpart to the age-based sweep above -- see its doc comment.
|
||||
OrphanDocumentIfUnreferenced(ctx context.Context, id int64) (bool, error)
|
||||
}
|
||||
|
||||
// DeleteOrphanedOlderThan implements maintenance.OrphanedMediaRetentionStore:
|
||||
|
|
@ -65,6 +68,33 @@ func (s *Service) DeleteOrphanedOlderThan(ctx context.Context, cutoff time.Time,
|
|||
return deleted, nil
|
||||
}
|
||||
|
||||
// deleteDocumentNowIfUnreferenced is the immediate counterpart to the
|
||||
// age-based sweep DeleteOrphanedOlderThan runs in the background: orphans
|
||||
// id right now (skipping the grace period) and, only if that succeeds --
|
||||
// i.e. nothing else currently references it -- physically deletes it and
|
||||
// its blobs immediately. Returns whether it was actually deleted; false
|
||||
// (with no error) means something still references the document, so it and
|
||||
// its blob(s) were deliberately left alone.
|
||||
func (s *Service) deleteDocumentNowIfUnreferenced(ctx context.Context, id int64) (bool, error) {
|
||||
store, ok := s.media.(mediaRetentionStore)
|
||||
if !ok {
|
||||
return false, nil
|
||||
}
|
||||
orphaned, err := store.OrphanDocumentIfUnreferenced(ctx, id)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("orphan document: %w", err)
|
||||
}
|
||||
if !orphaned {
|
||||
return false, nil
|
||||
}
|
||||
blobs, err := store.DeleteDocumentAndBlobs(ctx, id)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("delete document: %w", err)
|
||||
}
|
||||
s.deleteOrphanedBlobs(ctx, store, blobs)
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// deleteOrphanedBlobs removes each blob from its backend once confirming
|
||||
// (via CountFileBlobRefs) no other file_blobs row still references
|
||||
// (backend, object_key). Resolves the correct backend per blob via
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue