Skip to content
Back to home

CODING FINDS

Notes from the terminal.

Short write-ups of things I learned the hard way: the problem, the fix and the result, with the smallest snippet that shows it.

FOR CODING AGENTS

Every note is also available over MCP, so your coding agent can look up a fix before it writes the bug.

[MCP server URL]
All notes
Laravel

Let the queue drop duplicate jobs

Problem. Put a heavy job behind an "Export orders" button and every click queues another copy. Impatient users click two, three, ten times, and each click is another full export competing for the same workers and the same database.

Guarding the dispatch with a cache flag looks like a fix, but Cache::has() followed by Cache::put() is two separate steps, so two quick requests can both get past the check. The flag also outlives the job: it stays set after the export has finished, so the button does nothing until the flag expires.

Fix. Implement ShouldBeUnique on the job and return the key that defines a duplicate from uniqueId(). When the job is dispatched, Laravel takes an atomic cache lock named after the job class and that key. If the lock is already held, the new dispatch is dropped. The lock is released as soon as the job finishes, or once it has failed all of its retries.

The #[UniqueFor] attribute is the safety net. It releases the lock after that many seconds even if a worker dies halfway through, so one crash cannot block exports for good.

php
// Before: a flag that two quick clicks can both get pastif (! Cache::has("export:{$team->id}")) {    Cache::put("export:{$team->id}", true, 900);    ExportOrders::dispatch($team);}// After: the queue holds the lock#[UniqueFor(900)]class ExportOrders implements ShouldQueue, ShouldBeUnique{    use Queueable;    public function __construct(public Team $team) {}    // One export per team; other teams still run in parallel    public function uniqueId(): string    {        return (string) $this->team->id;    }    public function handle(): void    {        // Build and email the CSV...    }}// Ignored while this team's export is queued or runningExportOrders::dispatch($team);

Result. Extra clicks become no-ops instead of extra exports, and there is no flag to clear or forget. The lock lives in the cache, so use a store that supports atomic locks (Redis, Memcached, DynamoDB, database, file or array) and make sure every server shares it. If you only want to stop two copies running at once but still queue the second one, use the WithoutOverlapping job middleware instead.

Stuck on something like this?

Tell me what you are working on. I’ll help you find it, fix it and keep it fixed.

Book a call