diff --git a/apps/api/internal/store/admission_lock.go b/apps/api/internal/store/admission_lock.go index 970411c..ad9d9c5 100644 --- a/apps/api/internal/store/admission_lock.go +++ b/apps/api/internal/store/admission_lock.go @@ -115,18 +115,21 @@ func admissionOperationLockKeys(input TaskAdmissionInput) []string { } func tryAdmissionTransactionLock(ctx context.Context, tx pgx.Tx, key string) error { - var locked bool - if err := tx.QueryRow( + // The process-local lock limits this wait to one PostgreSQL connection per + // API or Worker process. Let PostgreSQL queue those process representatives + // fairly: repeated pg_try_advisory_xact_lock calls let a sustained submit + // burst starve the Worker dispatcher that must release queue pressure. + // lock_timeout bounds a lost-owner wait and converts it back into the + // existing transaction retry path. + _, err := tx.Exec( ctx, - `SELECT pg_try_advisory_xact_lock(hashtextextended($1, 0))`, + `SELECT pg_advisory_xact_lock(hashtextextended($1, 0))`, key, - ).Scan(&locked); err != nil { - return err - } - if !locked { + ) + if IsPostgresLockTimeout(err) { return errAdmissionLockBusy } - return nil + return err } func retryAdmissionOperation[T any](