When we get a DB error like a constraint violation, the message is dropped.
We're wrapping the lpop call that takes the message off the list in a predis MultiExec transaction along with the callback:
https://github.com/CoderKungfu/php-queue/blob/master/src/PHPQueue/Backend/Predis.php#L104
If there's an exception, the predis driver discards the transaction, leaving the message on the queue:
https://github.com/nrk/predis/blob/v1.1/src/Transaction/MultiExec.php#L430
But the exit() being called by Civi seems to break that. Why is the predis driver committing the txn? Is there an autocommit option set someplace?