GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — fix: make database job reservation atomic and always close the transaction by gr8man · Pull Request #104 · codeigniter4/queue

Conversation

@gr8man

@gr8man gr8man commented Nov 10, 2026

Copy link
Copy Markdown
Contributor

Description

QueueJobModel::popWithLock() reserves a job inside a transaction, but the transaction was not closed on every code path, and a successful reservation was never verified.

  1. Transaction leak. When the SELECT failed, the method returned null without calling transComplete(). The transaction depth stayed unbalanced, so a later transComplete() from an unrelated (nested) operation could commit or roll back work it did not own, and the connection remained inside an open transaction.
  2. Unconfirmed reservations. The result of the UPDATE that changes the job status to RESERVED was discarded. A job could therefore be returned to the worker (and processed) even though the status was never actually persisted, which allows two workers to process the same job.

Changes

  • src/Models/QueueJobModel.php
    • Wrapped the reservation in try { ... } finally { $this->db->transComplete(); } so the transaction is always closed, whichever path is taken.
    • The reservation is now confirmed with update() !== false && $this->db->affectedRows() === 1. When the reservation cannot be confirmed, the transaction is rolled back and null is returned, so the job stays PENDING and is never processed.
    • An empty result set (no pending job available) returns null before the update.

Testing

Added three cases to tests/Models/QueueJobModelTest.php:

  • testPopWithLockReturnsNullAndClosesTransactionWhenQueryFails() — after a failed query, transDepth is back to 0.
  • testPopWithLockRollsBackAndReturnsNullWhenUpdateFails() — when update() returns false, the method returns null, rolls back, and the row remains PENDING.
  • testPopWithLockRollsBackAndReturnsNullWhenAffectedRowsIsNotOne() — when the update affects no rows, the same rollback and PENDING state are asserted.

Verified locally on PHP 8.5 with PHPUnit 11.5:

phpunit ....... OK (233 tests, 655 assertions, 27 skipped)
phpstan ....... [OK] No errors
psalm ......... No errors found
php-cs-fixer .. 0 of 75 files would be fixed

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
gr8man added 2 commits November 10, 2026 21:35
@gr8man
fix: make database job reservation atomic and always close transaction
27fa6af
@gr8man
test: verify transaction rollback and closure in popWithLock on failure
1eb0b52

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@gr8man
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.