feat: add brand asset cleanup worker and related functionality
Frontend CI / Frontend (push) Successful in 3m23s
Backend CI / Backend (push) Failing after 6m46s

- 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:
2026-06-19 11:45:13 +08:00
parent 97ae601cfd
commit 6e0519a232
29 changed files with 1621 additions and 54 deletions
@@ -566,6 +566,7 @@ func loadExistingPublishRecordTargets(
AND pa.workspace_id = $2
AND pr.article_id = $3
AND pr.platform_account_id = ANY($4::bigint[])
AND pr.deleted_at IS NULL
AND pr.status IN ('queued', 'publishing', 'success')
AND dt.status IN ('queued', 'in_progress', 'succeeded', 'unknown')
ORDER BY pr.platform_account_id,
@@ -731,13 +732,18 @@ func (s *PublishJobService) RetryTenantDesktopTask(
if err != nil {
return nil, err
}
brandID, err := s.resolveRetryArticleBrandID(ctx, actor.TenantID, articleID)
if err != nil {
return nil, err
}
title := strings.TrimSpace(stringPointerValue(extractStringPointer(payload, "title")))
if title == "" {
title = "文章发布"
}
return s.Create(ctx, auth.Actor{
publishCtx := auth.WithCurrentBrandID(ctx, brandID)
return s.Create(publishCtx, auth.Actor{
TenantID: actor.TenantID,
UserID: actor.UserID,
PrimaryWorkspaceID: workspaceID,
@@ -895,7 +901,7 @@ func (s *PublishJobService) resolveRetryArticleID(ctx context.Context, tenantID
err := s.pool.QueryRow(ctx, `
SELECT article_id
FROM publish_records
WHERE id = $1 AND tenant_id = $2
WHERE id = $1 AND tenant_id = $2 AND deleted_at IS NULL
`, publishRecordID, tenantID).Scan(&articleID)
if err == nil && articleID > 0 {
return articleID, nil