Download the PHP package boring-o11y/unique-job-middleware without Composer

On this page you can find all versions of the php package boring-o11y/unique-job-middleware. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package unique-job-middleware

Unique Job Middleware

A queue job middleware that checks a ShouldBeUnique job's lock again when a worker picks it up, and skips the job if another job holds it.

Why

Laravel checks uniqueness in exactly one place: dispatch(). It takes the lock there, and if the lock is already held the dispatch is quietly discarded. Every other way onto the queue skips that check:

A unique job queued any of those ways runs even while another copy holds the lock, so two copies run side by side.

The middleware can't just check "is the lock held?". A normally dispatched job holds its own lock while it waits, so the middleware has to know whether the lock is this job's. Laravel takes the lock with a random owner token and throws the token away. This package records it in the payload so the middleware can compare.

Install

The service provider is discovered automatically. Then add new EnsureUniqueLock to the middleware() of each unique job you want protected.

What happens when the job is picked up

The job's unique lock is… Result
held by this job runs
free takes the lock, then runs
held by another job deleted without running; UniqueJobSkipped is fired
unreadable (store has no locks, Redis error) runs
not recorded (job queued before install) runs

A job is only skipped when there is proof another job holds its lock.

When a job takes a free lock, it takes it under the owner its payload records, or under its own uuid if it has none. If it is released back onto the queue, its next attempt still counts as the holder. For ShouldBeUnique jobs Laravel releases that lock when the job finishes, just as for a dispatched job.

Chains and batches

ShouldBeUniqueUntilProcessing

These jobs release their lock as they start, so the middleware never takes a free lock for them. It only skips a copy while another job still holds the lock.

On Laravel 10 and early 11.x, the framework releases that lock before middleware runs. An until-processing job therefore always finds its lock free there and runs. Plain ShouldBeUnique jobs are protected on every supported version.

Seeing skipped jobs

A skip is silent unless you listen for it. In Horizon, a skipped job shows as completed.

The event carries the queue job ($job), the job instance that didn't run ($command), and the lock key ($lockKey).

How it works

At push. A Queue::createPayloadUsing() hook adds a record to the payload of every unique job:

The hook runs before the job is serialized, so it sees the job instance. owner is filled in only when the push happens inside a dispatch that just took the lock: PendingDispatch, a unique queued listener, or the scheduler queueing a unique job. It is found with a backtrace, and only for unique jobs. Every other push records owner: null. A retry re-queues the stored payload, so the record comes with it.

At pickup. The middleware reads the record and compares it with the lock's current owner in the cache store.

On skip. Returning from middleware without calling $next isn't enough on its own. After middleware returns, Laravel's CallQueuedHandler force-releases the unique lock by key, and that lock belongs to the other job. So the middleware:

  1. deletes the job
  2. marks the queue job as released, which stops that release without putting the job back on the queue

That marker is a protected property on Illuminate\Queue\Jobs\Job, which every built-in queue driver's job extends.

Limits

Requirements

PHP 8.1+, Laravel 10–13. Works with any queue driver, and with Laravel Horizon.

Testing

The suite runs twice: once on Laravel's Redis queue, and once on Horizon's queue driver.

License

MIT


All versions of unique-job-middleware with dependencies

PHP Build Version
Package Version
Requires php Version ^8.1
illuminate/bus Version ^10.0|^11.0|^12.0|^13.0
illuminate/cache Version ^10.0|^11.0|^12.0|^13.0
illuminate/contracts Version ^10.0|^11.0|^12.0|^13.0
illuminate/queue Version ^10.0|^11.0|^12.0|^13.0
illuminate/support Version ^10.0|^11.0|^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package boring-o11y/unique-job-middleware contains the following files

Loading the files please wait ...