Skip to content

Instantly share code, notes, and snippets.

@stevebauman
Created December 3, 2025 00:06
Show Gist options
  • Select an option

  • Save stevebauman/6d469d319812360ac4ffdb6494b18501 to your computer and use it in GitHub Desktop.

Select an option

Save stevebauman/6d469d319812360ac4ffdb6494b18501 to your computer and use it in GitHub Desktop.
Laravel Job Middleware OnOneServer
<?php
namespace App\Jobs\Middleware;
use Closure;
use Illuminate\Contracts\Cache\Store;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\InteractsWithTime;
class OnOneServer
{
use InteractsWithTime;
/**
* The cache store that should be used.
*/
protected ?string $store = null;
/**
* The prefix of the lock key.
*/
public string $prefix = 'laravel-queue-one-server:';
/**
* Create a new middleware instance.
*/
public function __construct(
protected ?string $key = null,
protected ?string $server = null,
protected int $releaseAfter = 5,
protected int $expiresAfter = 600, // 10 minutes
) {
$this->server = $server ?? gethostname();
}
/**
* Process the queued job.
*
* @param Closure(object): void $next
*/
public function handle(object $job, Closure $next): void
{
// We're on the correct server, process the job.
if (gethostname() === $this->server) {
$this->forgetExpiryTime($this->cache(), $job);
$next($job);
return;
}
$cache = $this->cache();
$time = Date::now()->timestamp;
$expiryTime = $this->getExpiryTime($cache, $job);
// Expiry time reached, any worker can process the job.
if ($expiryTime && $time >= $expiryTime) {
$this->forgetExpiryTime($cache, $job);
$next($job);
return;
}
// We're not on the required server and the expiry hasn't been
// reached. Set the expiry time if not set, then release the
// job back to the queue for another worker to pick up.
if (! $expiryTime) {
$this->setExpiryTime($cache, $job, $time + $this->expiresAfter);
}
$job->release($this->releaseAfter);
}
/**
* Get the expiry time from cache.
*/
protected function getExpiryTime(Store $cache, object $job): ?int
{
return $cache->get(
$this->getLockKey($job).':expiry'
);
}
/**
* Set the expiry time in cache.
*/
protected function setExpiryTime(Store $cache, object $job, int $expiryTime): void
{
$cache->put(
$this->getLockKey($job).':expiry',
$expiryTime,
$this->expiresAfter
);
}
/**
* Forget the expiry time from cache.
*/
protected function forgetExpiryTime(Store $cache, object $job): void
{
$cache->forget($this->getLockKey($job).':expiry');
}
/**
* Get the lock key for the given job.
*/
protected function getLockKey(object $job): string
{
return $this->prefix.get_class($job).':'.$this->key;
}
/**
* Get the cache store that should be used.
*/
protected function cache(): Store
{
return Cache::store($this->store)->getStore();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment