feat: add brand asset cleanup worker and related functionality
- Implemented a new BrandAssetCleanupWorker to handle the cleanup of brand-related assets after a brand is deleted. - Added SQL queries for cleaning up articles, keywords, questions, competitors, and monitoring data associated with a brand. - Introduced a new API endpoint to delete publish records. - Updated the router to include the new delete publish record endpoint. - Added tests for the BrandAssetCleanupWorker to ensure proper functionality. - Created migration scripts to support soft deletion of publish records and to add the brand asset cleanup scheduler job.
This commit is contained in:
@@ -278,19 +278,38 @@ func (s *BrandService) Delete(ctx context.Context, id int64) error {
|
||||
_ = tx.Rollback(ctx)
|
||||
}()
|
||||
|
||||
tag, err := tx.Exec(ctx, `UPDATE brands SET deleted_at = NOW(), updated_at = NOW() WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL`, id, actor.TenantID)
|
||||
if err != nil || tag.RowsAffected() == 0 {
|
||||
return response.ErrNotFound(40420, "brand_not_found", "brand not found")
|
||||
tag, err := tx.Exec(ctx, `
|
||||
UPDATE brands
|
||||
SET status = 'deleting',
|
||||
deleted_at = COALESCE(deleted_at, NOW()),
|
||||
updated_at = NOW()
|
||||
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
|
||||
`, id, actor.TenantID)
|
||||
if err != nil {
|
||||
return response.ErrInternal(50010, "delete_failed", "failed to mark brand for deletion")
|
||||
}
|
||||
if tag.RowsAffected() == 0 {
|
||||
var alreadyDeleted bool
|
||||
if lookupErr := tx.QueryRow(ctx, `
|
||||
SELECT deleted_at IS NOT NULL
|
||||
FROM brands
|
||||
WHERE id = $1 AND tenant_id = $2
|
||||
`, id, actor.TenantID).Scan(&alreadyDeleted); lookupErr != nil {
|
||||
if errors.Is(lookupErr, pgx.ErrNoRows) {
|
||||
return response.ErrNotFound(40420, "brand_not_found", "brand not found")
|
||||
}
|
||||
return response.ErrInternal(50010, "delete_failed", "failed to inspect brand deletion state")
|
||||
}
|
||||
if !alreadyDeleted {
|
||||
return response.ErrNotFound(40420, "brand_not_found", "brand not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
_, _ = tx.Exec(ctx, `UPDATE brand_keywords SET deleted_at = NOW(), updated_at = NOW() WHERE brand_id = $1 AND tenant_id = $2 AND deleted_at IS NULL`, id, actor.TenantID)
|
||||
_, _ = tx.Exec(ctx, `UPDATE brand_questions SET deleted_at = NOW(), updated_at = NOW() WHERE brand_id = $1 AND tenant_id = $2 AND deleted_at IS NULL`, id, actor.TenantID)
|
||||
_, _ = tx.Exec(ctx, `UPDATE competitors SET deleted_at = NOW(), updated_at = NOW() WHERE brand_id = $1 AND tenant_id = $2 AND deleted_at IS NULL`, id, actor.TenantID)
|
||||
|
||||
if err := s.cleanupMonitoringAfterBrandDelete(ctx, actor.TenantID, id); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
afterJSON, _ := json.Marshal(map[string]interface{}{"id": id, "action": "cascade_soft_delete"})
|
||||
afterJSON, _ := json.Marshal(map[string]interface{}{"id": id, "status": "deleting", "cleanup": "background"})
|
||||
if err := tx.Commit(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user