fix article generation task status logging
This commit is contained in:
@@ -54,7 +54,7 @@ func main() {
|
|||||||
app.GenerationStreams,
|
app.GenerationStreams,
|
||||||
generationCfg,
|
generationCfg,
|
||||||
app.Config().LLM.MaxOutputTokens,
|
app.Config().LLM.MaxOutputTokens,
|
||||||
).WithCache(app.Cache).WithConfigProvider(generationProvider)
|
).WithCache(app.Cache).WithLogger(app.Logger).WithConfigProvider(generationProvider)
|
||||||
|
|
||||||
promptRuleSvc := tenantapp.NewPromptRuleGenerationService(
|
promptRuleSvc := tenantapp.NewPromptRuleGenerationService(
|
||||||
app.DB,
|
app.DB,
|
||||||
@@ -82,7 +82,7 @@ func main() {
|
|||||||
app.GenerationStreams,
|
app.GenerationStreams,
|
||||||
generationCfg,
|
generationCfg,
|
||||||
app.Config().LLM.MaxOutputTokens,
|
app.Config().LLM.MaxOutputTokens,
|
||||||
).WithCache(app.Cache).WithConfigProvider(generationProvider)
|
).WithCache(app.Cache).WithLogger(app.Logger).WithConfigProvider(generationProvider)
|
||||||
|
|
||||||
kolWorker := generateworker.NewKolGenerationWorker(
|
kolWorker := generateworker.NewKolGenerationWorker(
|
||||||
app.DB,
|
app.DB,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
||||||
sharedcache "github.com/geo-platform/tenant-api/internal/shared/cache"
|
sharedcache "github.com/geo-platform/tenant-api/internal/shared/cache"
|
||||||
@@ -38,6 +39,7 @@ type ArticleImitationService struct {
|
|||||||
cfg generationRuntimeConfig
|
cfg generationRuntimeConfig
|
||||||
configProvider runtimeConfigProvider
|
configProvider runtimeConfigProvider
|
||||||
cache sharedcache.Cache
|
cache sharedcache.Cache
|
||||||
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type GenerateImitationRequest struct {
|
type GenerateImitationRequest struct {
|
||||||
@@ -105,6 +107,11 @@ func (s *ArticleImitationService) WithConfigProvider(provider runtimeConfigProvi
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ArticleImitationService) WithLogger(logger *zap.Logger) *ArticleImitationService {
|
||||||
|
s.logger = logger
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ArticleImitationService) runtimeConfig() generationRuntimeConfig {
|
func (s *ArticleImitationService) runtimeConfig() generationRuntimeConfig {
|
||||||
if s != nil && s.configProvider != nil {
|
if s != nil && s.configProvider != nil {
|
||||||
if cfg := s.configProvider.Current(); cfg != nil {
|
if cfg := s.configProvider.Current(); cfg != nil {
|
||||||
@@ -460,15 +467,29 @@ func (s *ArticleImitationService) failGeneration(ctx context.Context, job articl
|
|||||||
articleRepo := repository.NewArticleRepository(s.pool)
|
articleRepo := repository.NewArticleRepository(s.pool)
|
||||||
quotaRepo := repository.NewQuotaRepository(s.pool)
|
quotaRepo := repository.NewQuotaRepository(s.pool)
|
||||||
|
|
||||||
_ = auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
if err := auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
||||||
ID: job.TaskID,
|
ID: job.TaskID,
|
||||||
TenantID: job.TenantID,
|
TenantID: job.TenantID,
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
ErrorMessage: &errMsg,
|
ErrorMessage: &errMsg,
|
||||||
CompletedAt: &now,
|
CompletedAt: &now,
|
||||||
})
|
}); err != nil && s.logger != nil {
|
||||||
|
s.logger.Warn("imitation generation task failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
if job.ArticleID > 0 {
|
if job.ArticleID > 0 {
|
||||||
_ = articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed")
|
if err := articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed"); err != nil && s.logger != nil {
|
||||||
|
s.logger.Warn("imitation generation article failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
_, _ = s.pool.Exec(cleanupCtx, `
|
_, _ = s.pool.Exec(cleanupCtx, `
|
||||||
UPDATE articles
|
UPDATE articles
|
||||||
SET wizard_state_json = jsonb_set(COALESCE(wizard_state_json, '{}'::jsonb), '{title}', to_jsonb($1::text), true),
|
SET wizard_state_json = jsonb_set(COALESCE(wizard_state_json, '{}'::jsonb), '{title}', to_jsonb($1::text), true),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package app
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -61,15 +62,20 @@ func HandleClaimedGenerationTaskFailure(
|
|||||||
articleRepo := repository.NewArticleRepository(pool)
|
articleRepo := repository.NewArticleRepository(pool)
|
||||||
quotaRepo := repository.NewQuotaRepository(pool)
|
quotaRepo := repository.NewQuotaRepository(pool)
|
||||||
|
|
||||||
_ = auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
var failureErr error
|
||||||
|
if err := auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
||||||
ID: task.ID,
|
ID: task.ID,
|
||||||
TenantID: task.TenantID,
|
TenantID: task.TenantID,
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
ErrorMessage: &errMsg,
|
ErrorMessage: &errMsg,
|
||||||
CompletedAt: &now,
|
CompletedAt: &now,
|
||||||
})
|
}); err != nil {
|
||||||
|
failureErr = errors.Join(failureErr, fmt.Errorf("update generation task failed status: %w", err))
|
||||||
|
}
|
||||||
if task.ArticleID > 0 {
|
if task.ArticleID > 0 {
|
||||||
_ = articleRepo.UpdateArticleGenerateStatus(cleanupCtx, task.ArticleID, task.TenantID, "failed")
|
if err := articleRepo.UpdateArticleGenerateStatus(cleanupCtx, task.ArticleID, task.TenantID, "failed"); err != nil {
|
||||||
|
failureErr = errors.Join(failureErr, fmt.Errorf("update article failed status: %w", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if task.QuotaReservationID > 0 {
|
if task.QuotaReservationID > 0 {
|
||||||
@@ -119,7 +125,7 @@ func HandleClaimedGenerationTaskFailure(
|
|||||||
promptRuleService.streams.Fail(task.ArticleID, task.ID, title, errMsg)
|
promptRuleService.streams.Fail(task.ArticleID, task.ID, title, errMsg)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return failureErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TemplateService) ProcessQueuedTask(ctx context.Context, task ClaimedGenerationTask) {
|
func (s *TemplateService) ProcessQueuedTask(ctx context.Context, task ClaimedGenerationTask) {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
@@ -389,14 +391,17 @@ func HandleKolGenerationTaskFailure(
|
|||||||
quotaRepo := repository.NewQuotaRepository(pool)
|
quotaRepo := repository.NewQuotaRepository(pool)
|
||||||
usageRepo := repository.NewKolUsageRepository(pool)
|
usageRepo := repository.NewKolUsageRepository(pool)
|
||||||
|
|
||||||
|
var failureErr error
|
||||||
if task.ID > 0 {
|
if task.ID > 0 {
|
||||||
_ = auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
if err := auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
||||||
ID: task.ID,
|
ID: task.ID,
|
||||||
TenantID: task.TenantID,
|
TenantID: task.TenantID,
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
ErrorMessage: &errMsg,
|
ErrorMessage: &errMsg,
|
||||||
CompletedAt: &now,
|
CompletedAt: &now,
|
||||||
})
|
}); err != nil {
|
||||||
|
failureErr = errors.Join(failureErr, fmt.Errorf("update generation task failed status: %w", err))
|
||||||
|
}
|
||||||
_ = auditRepo.UpdateTaskRecordStatus(cleanupCtx, repository.TaskRecordInput{
|
_ = auditRepo.UpdateTaskRecordStatus(cleanupCtx, repository.TaskRecordInput{
|
||||||
TenantID: task.TenantID,
|
TenantID: task.TenantID,
|
||||||
TaskType: kolGenerationTaskRecordType,
|
TaskType: kolGenerationTaskRecordType,
|
||||||
@@ -409,7 +414,9 @@ func HandleKolGenerationTaskFailure(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if task.ArticleID > 0 {
|
if task.ArticleID > 0 {
|
||||||
_ = articleRepo.UpdateArticleGenerateStatus(cleanupCtx, task.ArticleID, task.TenantID, "failed")
|
if err := articleRepo.UpdateArticleGenerateStatus(cleanupCtx, task.ArticleID, task.TenantID, "failed"); err != nil {
|
||||||
|
failureErr = errors.Join(failureErr, fmt.Errorf("update article failed status: %w", err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if task.QuotaReservationID > 0 {
|
if task.QuotaReservationID > 0 {
|
||||||
@@ -433,5 +440,5 @@ func HandleKolGenerationTaskFailure(
|
|||||||
}
|
}
|
||||||
|
|
||||||
InvalidateArticleCaches(cleanupCtx, cache, task.TenantID, &task.ArticleID)
|
InvalidateArticleCaches(cleanupCtx, cache, task.TenantID, &task.ArticleID)
|
||||||
return nil
|
return failureErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -695,14 +695,28 @@ func (s *PromptRuleGenerationService) failGeneration(ctx context.Context, job pr
|
|||||||
articleRepo := repository.NewArticleRepository(s.pool)
|
articleRepo := repository.NewArticleRepository(s.pool)
|
||||||
quotaRepo := repository.NewQuotaRepository(s.pool)
|
quotaRepo := repository.NewQuotaRepository(s.pool)
|
||||||
|
|
||||||
_ = auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
if err := auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
||||||
ID: job.TaskID,
|
ID: job.TaskID,
|
||||||
TenantID: job.TenantID,
|
TenantID: job.TenantID,
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
ErrorMessage: &errMsg,
|
ErrorMessage: &errMsg,
|
||||||
CompletedAt: &now,
|
CompletedAt: &now,
|
||||||
})
|
}); err != nil && s.logger != nil {
|
||||||
_ = articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed")
|
s.logger.Warn("prompt rule generation task failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err := articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed"); err != nil && s.logger != nil {
|
||||||
|
s.logger.Warn("prompt rule generation article failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
if failureTitle != "" {
|
if failureTitle != "" {
|
||||||
_, _ = s.pool.Exec(cleanupCtx, `
|
_, _ = s.pool.Exec(cleanupCtx, `
|
||||||
UPDATE articles
|
UPDATE articles
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jackc/pgx/v5"
|
"github.com/jackc/pgx/v5"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
"github.com/geo-platform/tenant-api/internal/shared/auth"
|
||||||
sharedcache "github.com/geo-platform/tenant-api/internal/shared/cache"
|
sharedcache "github.com/geo-platform/tenant-api/internal/shared/cache"
|
||||||
@@ -31,6 +32,7 @@ type TemplateService struct {
|
|||||||
cfg generationRuntimeConfig
|
cfg generationRuntimeConfig
|
||||||
configProvider runtimeConfigProvider
|
configProvider runtimeConfigProvider
|
||||||
cache sharedcache.Cache
|
cache sharedcache.Cache
|
||||||
|
logger *zap.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type generationJob struct {
|
type generationJob struct {
|
||||||
@@ -80,6 +82,11 @@ func (s *TemplateService) WithConfigProvider(provider runtimeConfigProvider) *Te
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *TemplateService) WithLogger(logger *zap.Logger) *TemplateService {
|
||||||
|
s.logger = logger
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
func (s *TemplateService) runtimeConfig() generationRuntimeConfig {
|
func (s *TemplateService) runtimeConfig() generationRuntimeConfig {
|
||||||
if s != nil && s.configProvider != nil {
|
if s != nil && s.configProvider != nil {
|
||||||
if cfg := s.configProvider.Current(); cfg != nil {
|
if cfg := s.configProvider.Current(); cfg != nil {
|
||||||
@@ -584,14 +591,28 @@ func (s *TemplateService) failGeneration(ctx context.Context, job generationJob,
|
|||||||
articleRepo := repository.NewArticleRepository(s.pool)
|
articleRepo := repository.NewArticleRepository(s.pool)
|
||||||
quotaRepo := repository.NewQuotaRepository(s.pool)
|
quotaRepo := repository.NewQuotaRepository(s.pool)
|
||||||
|
|
||||||
_ = auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
if err := auditRepo.UpdateGenerationTaskStatus(cleanupCtx, repository.GenerationTaskStatusInput{
|
||||||
ID: job.TaskID,
|
ID: job.TaskID,
|
||||||
TenantID: job.TenantID,
|
TenantID: job.TenantID,
|
||||||
Status: "failed",
|
Status: "failed",
|
||||||
ErrorMessage: &errMsg,
|
ErrorMessage: &errMsg,
|
||||||
CompletedAt: &now,
|
CompletedAt: &now,
|
||||||
})
|
}); err != nil && s.logger != nil {
|
||||||
_ = articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed")
|
s.logger.Warn("template generation task failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if err := articleRepo.UpdateArticleGenerateStatus(cleanupCtx, job.ArticleID, job.TenantID, "failed"); err != nil && s.logger != nil {
|
||||||
|
s.logger.Warn("template generation article failed status update failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", job.TaskID),
|
||||||
|
zap.Int64("article_id", job.ArticleID),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
balance, balanceErr := quotaRepo.GetCurrentBalance(cleanupCtx, job.TenantID, "article_generation")
|
balance, balanceErr := quotaRepo.GetCurrentBalance(cleanupCtx, job.TenantID, "article_generation")
|
||||||
if balanceErr == nil {
|
if balanceErr == nil {
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ func (q *Queries) CreateTaskRecord(ctx context.Context, arg CreateTaskRecordPara
|
|||||||
}
|
}
|
||||||
|
|
||||||
const updateGenerationTaskStatus = `-- name: UpdateGenerationTaskStatus :exec
|
const updateGenerationTaskStatus = `-- name: UpdateGenerationTaskStatus :exec
|
||||||
UPDATE generation_tasks SET status = $1, error_message = $2,
|
UPDATE generation_tasks SET status = $1::text, error_message = $2,
|
||||||
started_at = $3,
|
started_at = $3,
|
||||||
completed_at = $4,
|
completed_at = $4,
|
||||||
lease_token = CASE WHEN $1::text IN ('completed', 'failed') THEN NULL ELSE lease_token END,
|
lease_token = CASE WHEN $1::text IN ('completed', 'failed') THEN NULL ELSE lease_token END,
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ WHERE tenant_id = sqlc.arg(tenant_id)
|
|||||||
AND resource_id = sqlc.arg(resource_id);
|
AND resource_id = sqlc.arg(resource_id);
|
||||||
|
|
||||||
-- name: UpdateGenerationTaskStatus :exec
|
-- name: UpdateGenerationTaskStatus :exec
|
||||||
UPDATE generation_tasks SET status = sqlc.arg(status), error_message = sqlc.arg(error_message),
|
UPDATE generation_tasks SET status = sqlc.arg(status)::text, error_message = sqlc.arg(error_message),
|
||||||
started_at = sqlc.arg(started_at),
|
started_at = sqlc.arg(started_at),
|
||||||
completed_at = sqlc.arg(completed_at),
|
completed_at = sqlc.arg(completed_at),
|
||||||
lease_token = CASE WHEN sqlc.arg(status)::text IN ('completed', 'failed') THEN NULL ELSE lease_token END,
|
lease_token = CASE WHEN sqlc.arg(status)::text IN ('completed', 'failed') THEN NULL ELSE lease_token END,
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ func NewArticleHandler(a *bootstrap.App) *ArticleHandler {
|
|||||||
a.GenerationStreams,
|
a.GenerationStreams,
|
||||||
a.Config().Generation,
|
a.Config().Generation,
|
||||||
a.Config().LLM.MaxOutputTokens,
|
a.Config().LLM.MaxOutputTokens,
|
||||||
).WithCache(a.Cache).WithConfigProvider(a.ConfigStore),
|
).WithCache(a.Cache).WithLogger(a.Logger).WithConfigProvider(a.ConfigStore),
|
||||||
streams: a.GenerationStreams,
|
streams: a.GenerationStreams,
|
||||||
app: a,
|
app: a,
|
||||||
assets: NewAssetHandler(a),
|
assets: NewAssetHandler(a),
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func NewTemplateHandler(a *bootstrap.App) *TemplateHandler {
|
|||||||
a.GenerationStreams,
|
a.GenerationStreams,
|
||||||
a.Config().Generation,
|
a.Config().Generation,
|
||||||
a.Config().LLM.MaxOutputTokens,
|
a.Config().LLM.MaxOutputTokens,
|
||||||
).WithCache(a.Cache).WithConfigProvider(a.ConfigStore),
|
).WithCache(a.Cache).WithLogger(a.Logger).WithConfigProvider(a.ConfigStore),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -472,11 +472,44 @@ func (w *ArticleGenerationWorker) requeueExpiredRunningGenerationTask(ctx contex
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
tenantID int64
|
tenantID int64
|
||||||
articleID int64
|
articleID int64
|
||||||
taskType string
|
taskType string
|
||||||
|
shouldRequeue bool
|
||||||
)
|
)
|
||||||
if err := tx.QueryRow(ctx, `
|
if err := tx.QueryRow(ctx, `
|
||||||
|
WITH existing AS (
|
||||||
|
SELECT gt.id,
|
||||||
|
gt.tenant_id,
|
||||||
|
gt.article_id,
|
||||||
|
gt.task_type,
|
||||||
|
a.generate_status
|
||||||
|
FROM generation_tasks gt
|
||||||
|
JOIN articles a ON a.id = gt.article_id
|
||||||
|
AND a.tenant_id = gt.tenant_id
|
||||||
|
WHERE gt.id = $1
|
||||||
|
AND gt.status = 'running'
|
||||||
|
AND (
|
||||||
|
gt.lease_expires_at IS NULL
|
||||||
|
OR gt.lease_expires_at < NOW()
|
||||||
|
)
|
||||||
|
FOR UPDATE OF gt
|
||||||
|
),
|
||||||
|
finalized_failed_article AS (
|
||||||
|
UPDATE generation_tasks gt
|
||||||
|
SET status = 'failed',
|
||||||
|
error_message = COALESCE(NULLIF(gt.error_message, ''), '文章已标记生成失败,停止后台恢复重试 [article_failed_stop_retry]'),
|
||||||
|
completed_at = COALESCE(gt.completed_at, NOW()),
|
||||||
|
lease_token = NULL,
|
||||||
|
lease_owner = NULL,
|
||||||
|
lease_expires_at = NULL,
|
||||||
|
updated_at = NOW()
|
||||||
|
FROM existing e
|
||||||
|
WHERE gt.id = e.id
|
||||||
|
AND e.generate_status = 'failed'
|
||||||
|
RETURNING e.tenant_id, e.article_id, e.task_type, false AS should_requeue
|
||||||
|
),
|
||||||
|
requeued AS (
|
||||||
UPDATE generation_tasks
|
UPDATE generation_tasks
|
||||||
SET status = 'queued',
|
SET status = 'queued',
|
||||||
error_message = NULL,
|
error_message = NULL,
|
||||||
@@ -484,14 +517,17 @@ func (w *ArticleGenerationWorker) requeueExpiredRunningGenerationTask(ctx contex
|
|||||||
lease_owner = NULL,
|
lease_owner = NULL,
|
||||||
lease_expires_at = NULL,
|
lease_expires_at = NULL,
|
||||||
updated_at = NOW()
|
updated_at = NOW()
|
||||||
WHERE id = $1
|
FROM existing e
|
||||||
AND status = 'running'
|
WHERE generation_tasks.id = e.id
|
||||||
AND (
|
AND e.generate_status <> 'failed'
|
||||||
lease_expires_at IS NULL
|
RETURNING e.tenant_id, e.article_id, e.task_type, true AS should_requeue
|
||||||
OR lease_expires_at < NOW()
|
)
|
||||||
)
|
SELECT tenant_id, article_id, task_type, should_requeue
|
||||||
RETURNING tenant_id, article_id, task_type
|
FROM finalized_failed_article
|
||||||
`, item.ID).Scan(&tenantID, &articleID, &taskType); err != nil {
|
UNION ALL
|
||||||
|
SELECT tenant_id, article_id, task_type, should_requeue
|
||||||
|
FROM requeued
|
||||||
|
`, item.ID).Scan(&tenantID, &articleID, &taskType, &shouldRequeue); err != nil {
|
||||||
if err == pgx.ErrNoRows {
|
if err == pgx.ErrNoRows {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
@@ -501,6 +537,15 @@ func (w *ArticleGenerationWorker) requeueExpiredRunningGenerationTask(ctx contex
|
|||||||
if err := tx.Commit(ctx); err != nil {
|
if err := tx.Commit(ctx); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
if !shouldRequeue {
|
||||||
|
if w.logger != nil {
|
||||||
|
w.logger.Info("article generation expired task finalized because article is already failed",
|
||||||
|
zap.Int64("task_id", item.ID),
|
||||||
|
zap.Int64("article_id", articleID),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
if err := w.publishGenerationTask(ctx, item.ID, taskType, tenantID, articleID); err != nil {
|
if err := w.publishGenerationTask(ctx, item.ID, taskType, tenantID, articleID); err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,13 +245,23 @@ func articleGenerationProcessTimeout(cfg config.GenerationConfig) time.Duration
|
|||||||
|
|
||||||
func (w *ArticleGenerationWorker) handleTaskFailure(ctx context.Context, task tenantapp.ClaimedGenerationTask, stage string, taskErr error) {
|
func (w *ArticleGenerationWorker) handleTaskFailure(ctx context.Context, task tenantapp.ClaimedGenerationTask, stage string, taskErr error) {
|
||||||
task.TaskType = strings.TrimSpace(task.TaskType)
|
task.TaskType = strings.TrimSpace(task.TaskType)
|
||||||
|
var err error
|
||||||
switch {
|
switch {
|
||||||
case task.TaskType == kolGenerationTaskType && w.kolWorker != nil:
|
case task.TaskType == kolGenerationTaskType && w.kolWorker != nil:
|
||||||
w.kolWorker.HandleTaskFailure(ctx, task, stage, taskErr)
|
w.kolWorker.HandleTaskFailure(ctx, task, stage, taskErr)
|
||||||
case task.TaskType == "imitation" && w.imitationService != nil:
|
case task.TaskType == "imitation" && w.imitationService != nil:
|
||||||
w.imitationService.HandleTaskFailure(ctx, task, stage, taskErr)
|
w.imitationService.HandleTaskFailure(ctx, task, stage, taskErr)
|
||||||
default:
|
default:
|
||||||
_ = tenantapp.HandleClaimedGenerationTaskFailure(ctx, w.pool, w.templateService, w.promptRuleService, task, taskErr)
|
err = tenantapp.HandleClaimedGenerationTaskFailure(ctx, w.pool, w.templateService, w.promptRuleService, task, taskErr)
|
||||||
|
}
|
||||||
|
if err != nil && w.logger != nil {
|
||||||
|
w.logger.Warn("article generation task failure handling failed",
|
||||||
|
zap.Error(err),
|
||||||
|
zap.Int64("task_id", task.ID),
|
||||||
|
zap.Int64("article_id", task.ArticleID),
|
||||||
|
zap.String("task_type", task.TaskType),
|
||||||
|
zap.String("stage", stage),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE generation_tasks
|
||||||
|
ALTER COLUMN status TYPE VARCHAR(20);
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
ALTER TABLE generation_tasks
|
||||||
|
ALTER COLUMN status TYPE TEXT;
|
||||||
Reference in New Issue
Block a user