You've already forked agentic-coding-workflow
bugfix
This commit is contained in:
+38
-13
@@ -22,9 +22,13 @@ import (
|
||||
type Repository interface {
|
||||
Enqueue(ctx context.Context, typ JobType, payload json.RawMessage, scheduledAt time.Time, maxAttempts int32) (*Job, error)
|
||||
Lease(ctx context.Context, leasedBy string) (*Job, error)
|
||||
Complete(ctx context.Context, id uuid.UUID) error
|
||||
FailWithRetry(ctx context.Context, id uuid.UUID, scheduledAt time.Time, lastErr string) error
|
||||
DeadLetter(ctx context.Context, id uuid.UUID, lastErr string) error
|
||||
// Complete, FailWithRetry and DeadLetter take the leasing worker id and apply
|
||||
// a fencing predicate (id + leased_by + status='running'); if the lease has
|
||||
// been lost (e.g. the reaper re-leased the job) they return ErrLeaseLost so
|
||||
// the caller drops the write instead of clobbering the new run's state.
|
||||
Complete(ctx context.Context, id uuid.UUID, leasedBy string) error
|
||||
FailWithRetry(ctx context.Context, id uuid.UUID, leasedBy string, scheduledAt time.Time, lastErr string) error
|
||||
DeadLetter(ctx context.Context, id uuid.UUID, leasedBy string, lastErr string) error
|
||||
Get(ctx context.Context, id uuid.UUID) (*Job, error)
|
||||
ReapStuckRunningJobs(ctx context.Context, leasedBefore time.Time) ([]uuid.UUID, error)
|
||||
PurgeCompleted(ctx context.Context, completedBefore time.Time) (int64, error)
|
||||
@@ -90,11 +94,20 @@ func (r *PgRepository) Lease(ctx context.Context, leasedBy string) (*Job, error)
|
||||
return rowToJob(row), nil
|
||||
}
|
||||
|
||||
// Complete marks a job as completed and clears its lease/error fields.
|
||||
func (r *PgRepository) Complete(ctx context.Context, id uuid.UUID) error {
|
||||
if err := r.q.CompleteJob(ctx, toPgUUID(id)); err != nil {
|
||||
// Complete marks a job as completed and clears its lease/error fields. The
|
||||
// update is fenced on the leasing worker id and status='running'; if no row
|
||||
// matches (lease lost to the reaper) it returns ErrLeaseLost as a no-op signal.
|
||||
func (r *PgRepository) Complete(ctx context.Context, id uuid.UUID, leasedBy string) error {
|
||||
n, err := r.q.CompleteJob(ctx, jobssqlc.CompleteJobParams{
|
||||
ID: toPgUUID(id),
|
||||
LeasedBy: &leasedBy,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.Wrap(err, errs.CodeInternal, "complete job")
|
||||
}
|
||||
if n == 0 {
|
||||
return ErrLeaseLost
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -102,25 +115,37 @@ func (r *PgRepository) Complete(ctx context.Context, id uuid.UUID) error {
|
||||
// the last error. Attempts is preserved (it was incremented on lease) so the
|
||||
// worker can compare against MaxAttempts to decide whether to retry or
|
||||
// dead-letter on the next failure.
|
||||
func (r *PgRepository) FailWithRetry(ctx context.Context, id uuid.UUID, scheduledAt time.Time, lastErr string) error {
|
||||
if err := r.q.FailJobWithRetry(ctx, jobssqlc.FailJobWithRetryParams{
|
||||
func (r *PgRepository) FailWithRetry(ctx context.Context, id uuid.UUID, leasedBy string, scheduledAt time.Time, lastErr string) error {
|
||||
n, err := r.q.FailJobWithRetry(ctx, jobssqlc.FailJobWithRetryParams{
|
||||
ID: toPgUUID(id),
|
||||
ScheduledAt: pgtype.Timestamptz{Time: scheduledAt, Valid: true},
|
||||
LastError: &lastErr,
|
||||
}); err != nil {
|
||||
LeasedBy: &leasedBy,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.Wrap(err, errs.CodeInternal, "fail job with retry")
|
||||
}
|
||||
if n == 0 {
|
||||
return ErrLeaseLost
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeadLetter terminally marks a job as dead and stores the last error.
|
||||
func (r *PgRepository) DeadLetter(ctx context.Context, id uuid.UUID, lastErr string) error {
|
||||
if err := r.q.DeadLetterJob(ctx, jobssqlc.DeadLetterJobParams{
|
||||
// DeadLetter terminally marks a job as dead and stores the last error. Fenced
|
||||
// on the leasing worker id and status='running'; returns ErrLeaseLost on a
|
||||
// 0-row match so a stale worker does not overwrite a re-leased run.
|
||||
func (r *PgRepository) DeadLetter(ctx context.Context, id uuid.UUID, leasedBy string, lastErr string) error {
|
||||
n, err := r.q.DeadLetterJob(ctx, jobssqlc.DeadLetterJobParams{
|
||||
ID: toPgUUID(id),
|
||||
LastError: &lastErr,
|
||||
}); err != nil {
|
||||
LeasedBy: &leasedBy,
|
||||
})
|
||||
if err != nil {
|
||||
return errs.Wrap(err, errs.CodeInternal, "dead-letter job")
|
||||
}
|
||||
if n == 0 {
|
||||
return ErrLeaseLost
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user