perf(worker): 消除运行态计数跨城热行阻塞

将仅用于候选负载均衡的 runtime_client_states 分配和释放写入改为事务级异步提交,避免同步复制期间持续持有单候选热行锁。\n\n运行态计数仍由本地 WAL 持久化,并在运行时恢复中按 running attempt 重建;任务、账务、租约和状态提交不受影响。新增 PostgreSQL 并发与恢复集成测试。\n\n验证:go vet ./...;go test ./... -count=1;64 并发 PostgreSQL 集成测试;迁移安全检查;gofmt;git diff --check。
This commit is contained in:
2026-07-31 09:14:13 +08:00
parent b0dac9f8ec
commit 11ec057e6a
3 changed files with 173 additions and 6 deletions
+33 -6
View File
@@ -2156,7 +2156,19 @@ ON CONFLICT (task_id, seq, callback_url) DO NOTHING`,
}
func (s *Store) RecordClientAssignment(ctx context.Context, candidate RuntimeModelCandidate) error {
_, err := s.pool.Exec(ctx, `
tx, err := s.pool.Begin(ctx)
if err != nil {
return err
}
defer rollbackTransaction(tx)
// This counter only influences candidate load balancing and is rebuilt from
// active attempts during runtime recovery. Keeping a synchronous-replication
// commit open while updating one row per upstream client serializes every
// assignment for a hot model across regions.
if _, err := tx.Exec(ctx, `SET LOCAL synchronous_commit = off`); err != nil {
return err
}
if _, err := tx.Exec(ctx, `
INSERT INTO runtime_client_states (
client_id, platform_id, provider, method_name, queue_key, running_count, last_assigned_at
)
@@ -2170,16 +2182,31 @@ SET running_count = runtime_client_states.running_count + 1,
candidate.Provider,
candidate.ModelType,
candidate.QueueKey,
)
return err
); err != nil {
return err
}
return tx.Commit(ctx)
}
func (s *Store) RecordClientRelease(ctx context.Context, clientID string, lastError string) error {
_, err := s.pool.Exec(ctx, `
tx, err := s.pool.Begin(ctx)
if err != nil {
return err
}
defer rollbackTransaction(tx)
// runtime_client_states is derived scheduler state; see
// RecordClientAssignment for why it must not hold its hot row lock through
// a cross-region synchronous replication wait.
if _, err := tx.Exec(ctx, `SET LOCAL synchronous_commit = off`); err != nil {
return err
}
if _, err := tx.Exec(ctx, `
UPDATE runtime_client_states
SET running_count = GREATEST(running_count - 1, 0),
last_error = NULLIF($2::text, ''),
updated_at = now()
WHERE client_id = $1`, clientID, lastError)
return err
WHERE client_id = $1`, clientID, lastError); err != nil {
return err
}
return tx.Commit(ctx)
}