Skip to content

Add Release queue middleware#60630

Merged
taylorotwell merged 2 commits into
laravel:13.xfrom
mgcodeur:feat/release-job-middleware
Jul 2, 2026
Merged

Add Release queue middleware#60630
taylorotwell merged 2 commits into
laravel:13.xfrom
mgcodeur:feat/release-job-middleware

Conversation

@mgcodeur

@mgcodeur mgcodeur commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Adds a Release queue middleware that releases a job back onto the queue based on a condition, instead of executing it immediately.

Where Skip deletes the job, Release defers its execution to a later attempt.

Example usage:

use Illuminate\Queue\Middleware\Release;

public function middleware(): array
{
    return [
        Release::when(
            fn () => ! $this->order->isPaid(),
            releaseAfter: 60
        ),
    ];
}

Release::when($condition) releases the job when the condition is truthy.
Release::unless($condition) releases the job when the condition is not truthy.
$releaseAfter defines the delay, in seconds, before the job is executed again.

mgcodeur added 2 commits June 30, 2026 19:14
Adds a `Release` queue middleware that releases a job back onto the queue
based on a condition, instead of executing it immediately. Where `Skip`
deletes the job, `Release` defers its execution to a later attempt.

Example usage:

```php
use Illuminate\Queue\Middleware\Release;

public function middleware(): array
{
    return [
        Release::when(
            fn () => ! $this->order->isPaid(),
            retryAfter: 60
        ),
    ];
}
```

`Release::when($condition)` releases the job when the condition is truthy.
`Release::unless($condition)` releases the job when the condition is not
truthy. `$retryAfter` defines the delay, in seconds, before the job is
executed again.
@mgcodeur

Copy link
Copy Markdown
Contributor Author

Here is a real-world use case from a music distribution system I'm working on.

When an initial delivery is performed, it can remain in progress for several hours while waiting for confirmation from the platforms. During this period, the user can trigger a takedown; the takedown must not run while the delivery is still in progress. The reverse is also true: a delivery for the same release must not start while a takedown is in progress.

use Illuminate\Queue\Middleware\Release;
public function middleware(): array
{
    return [
        Release::when(
            fn () => $this->release->hasPendingInitialDelivery(),
            releaseAfter: 300
        ),
    ];
}

In this case, the middleware simply defers the job until the opposing operation has finished.

This doesn't really match the role of WithoutOverlapping, which relies on a temporary lock held only while a job is executing. Here, we're instead checking a persistent domain state, which can remain active across multiple attempts.

@taylorotwell taylorotwell merged commit f6bad73 into laravel:13.x Jul 2, 2026
53 checks passed
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