fix(worker): 防止事务泄漏并恢复滞留队列

为 PostgreSQL 连接增加可配置的事务空闲与锁等待超时,并在请求取消或 Worker 退出后使用独立有界上下文回滚事务。\n\n恢复过期任务时按批次使用 SKIP LOCKED,周期重建缺失或终态 River Job;锁等待超时只在确认尚未提交上游时安全重排,避免重复执行和重复结算。\n\n验证:完整 Go 测试、go vet、生产 Kustomize 渲染、gofmt 与 git diff --check 均通过。
This commit is contained in:
2026-07-30 17:27:11 +08:00
parent bc44af751e
commit 6bab0f0749
32 changed files with 545 additions and 106 deletions
@@ -185,7 +185,7 @@ func (s *Store) CreateSecurityEventConnection(ctx context.Context, input CreateS
if err != nil {
return SecurityEventConnection{}, err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
_, err = tx.Exec(ctx, `
INSERT INTO gateway_security_event_connections(
connection_id,transmitter_issuer,endpoint_url,credential_ref,management_client_id,management_credential_ref,lifecycle_status,idempotency_key
@@ -196,7 +196,7 @@ INSERT INTO gateway_security_event_connections(
)
if err != nil {
if isUniqueViolation(err) {
_ = tx.Rollback(ctx)
rollbackTransaction(tx)
existing, getErr := s.SecurityEventConnection(ctx)
if getErr == nil && existing.IdempotencyKey == input.IdempotencyKey && existing.TransmitterIssuer == input.TransmitterIssuer {
return existing, nil
@@ -256,7 +256,7 @@ func (s *Store) SetSecurityEventManagementCredential(ctx context.Context, connec
if err != nil {
return SecurityEventConnection{}, err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
var oldReference sql.NullString
var lifecycle string
var version int64
@@ -315,7 +315,7 @@ func (s *Store) SetSecurityEventNextCredential(ctx context.Context, connectionID
if err != nil {
return SecurityEventConnection{}, err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
tag, err := tx.Exec(ctx, `UPDATE gateway_security_event_connections
SET next_credential_ref=$2,lifecycle_status='rotating',last_error_category=NULL,version=version+1,updated_at=now()
WHERE connection_id=$1::uuid AND version=$3 AND next_credential_ref IS NULL
@@ -340,7 +340,7 @@ func (s *Store) PromoteSecurityEventCredential(ctx context.Context, connectionID
if err != nil {
return SecurityEventConnection{}, err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
var oldReference string
if err := tx.QueryRow(ctx, `SELECT credential_ref FROM gateway_security_event_connections
WHERE connection_id=$1::uuid AND next_credential_ref=$2 AND lifecycle_status='rotating' FOR UPDATE`, connectionID, nextReference).Scan(&oldReference); errors.Is(err, pgx.ErrNoRows) {
@@ -381,7 +381,7 @@ func (s *Store) DiscardPreparedSecurityEventConnection(ctx context.Context, conn
if err != nil {
return err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
var credentialReference string
var nextReference, managementReference sql.NullString
@@ -435,7 +435,7 @@ func (s *Store) FinalizeRetiringSecurityEventConnection(ctx context.Context, con
if err != nil {
return err
}
defer tx.Rollback(ctx)
defer rollbackTransaction(tx)
var credentialReference string
var nextReference, managementReference sql.NullString