Skip to content

test: add release-based queue retry example (framework#1531) - #139

Merged
hwbrzzl merged 4 commits into
masterfrom
bowen/queue-release-retry
Aug 5, 2026
Merged

test: add release-based queue retry example (framework#1531)#139
hwbrzzl merged 4 commits into
masterfrom
bowen/queue-release-retry

Conversation

@goravel-coder

@goravel-coder goravel-coder commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Retry a failed job by releasing it back to the queue (attempt count preserved) instead of retrying in-process, powered by goravel/framework (PR #1531) and goravel/redis (PR #149); TestRetryable fails the first two attempts and succeeds on the third.
  • Bump goravel/framework to c0b610b so the database queue driver preserves sub-second backoff delays (time.Time.Add) and the jobs-table migration stores reserved_at/available_at/created_at with millisecond precision (DateTimeTz(col, 3)); the broadcast backoff test now asserts real 100ms/200ms delays instead of whole-second stand-ins.
  • Add retry_after to the database, redis1, and redis queue connections so a crashed worker's reservation expires and the job is recovered by other workers, and cover the retry-exhausted path via TestReleaseBasedRetryExhausted, which lands the job in failed_jobs once ShouldRetry gives up.

Why

Goravel's queue now supports release-based retries: when a job implements queue.JobWithShouldRetry and fails, it is released back to the queue with its attempt count preserved instead of being retried purely in-process, so retries survive worker restarts and can be picked up by any worker. The example repo consumes the framework changes that enable this, declares the retry_after reservation-expiry window required by the drivers, and demonstrates the flow with a job that fails the first two attempts and succeeds on the third — while also proving the exhausted path lands the job in failed_jobs.

Sub-second backoff now works end to end: the framework's database driver keeps the full delay (time.Time.Add) and the jobs table stores available_at with millisecond precision, so the earlier whole-second workaround was reverted and the tests exercise the real 100ms/200ms delays. The example migration matches the framework stub so the reference is copy-safe for production databases, and the self-pin replace directive for goravel/framework in go.mod is restored so the example consistently builds against the framework revision it demonstrates.

// app/jobs/test_retryable.go
package jobs

import (
	"errors"
	"time"
)

type TestRetryable struct{}

func (r *TestRetryable) Signature() string {
	return "test_retryable"
}

// Handle fails while the attempt count is within the failure window.
func (r *TestRetryable) Handle(args ...any) error {
	return errors.New("test retryable error")
}

// ShouldRetry releases the job back to the queue on failure with its attempt
// count preserved, so retries survive worker restarts. The 100ms delay is
// preserved by the database driver (millisecond precision).
func (r *TestRetryable) ShouldRetry(err error, attempt int) (bool, time.Duration) {
	if attempt <= 2 {
		return true, 100 * time.Millisecond
	}

	return false, 0
}

@goravel-coder
goravel-coder requested a review from a team as a code owner August 4, 2026 09:10
@hwbrzzl
hwbrzzl merged commit feaf1b8 into master Aug 5, 2026
9 checks passed
@hwbrzzl
hwbrzzl deleted the bowen/queue-release-retry branch August 5, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants