Get CV

Queue

Queue and schedule are two processes

A long job cannot delay a cron tick. A deploy restarts the worker so new jobs never run on old classes.

The compose file already had a queue container and a schedule container. Treating them as one process was the bug. A sitemap rebuild that ran inline stole the minute tick. A reserved job that unserialized a fat payload grew RSS until the host swapped. php-fpm should never see that work.

Workers now have a bounded attempt count, a timeout shorter than the Redis reservation, and a memory cap that kills the process before the box swaps. Slow work goes to the queue. The schedule process only dispatches.

Three processes. Three jobs. One host memory budget.
Three processes. Three jobs. One host memory budget.

Overlap and age

Tasks that can run long skip if the previous run is still active. Two copies of a nightly cleanup on the same rows is how you get a unique key error at 03:10. The health signal is a heartbeat on every tick. If the timestamp is older than a few minutes, the container is dead or wedged.

Alerts fire on oldest job age, not on depth. A deep queue that drains is fine. One stuck job is not. Failed jobs keep the payload, the exception class, and the correlation id of the request that queued them.

Overlap skip if the previous tick is still running. Alert on oldest job age, not depth.
Overlap skip if the previous tick is still running. Alert on oldest job age, not depth.

Deploys

A release restarts the queue worker explicitly. Without that step the worker keeps old classes in memory and processes new jobs with stale code. That bug lasted a few minutes after each flip and looked like a random failure.

The split is the rule. HTTP stays in php-fpm. Jobs stay in queue. Ticks stay in schedule. If a task is slow, it does not run on the tick.

Back to news