Skip to content

[7.x] Fix bulk operation queue deadlock under a flood of webhooks - #226

Merged
nfourtythree merged 2 commits into
7.xfrom
bugfix/224-bulk-operation-deadlock
Sep 9, 2026
Merged

nfourtythree merged 2 commits into
7.xfrom
bugfix/224-bulk-operation-deadlock

Conversation

@nfourtythree

Copy link
Copy Markdown
Contributor

Description

Related issues

#224

@nfourtythree nfourtythree self-assigned this Sep 8, 2026
@nfourtythree
nfourtythree requested a review from a team as a code owner September 8, 2026 09:43
@nfourtythree nfourtythree changed the title Fix bulk operation queue deadlock under a flood of webhooks [7.x] Fix bulk operation queue deadlock under a flood of webhooks Sep 8, 2026
@nfourtythree
nfourtythree requested a lite review from Copilot September 8, 2026 14:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The concurrency fix is covered by targeted regression tests and the schema/migration updates appear consistent with the new Failed status behavior.

Pull request overview

This PR addresses a bulk operation queue deadlock that can occur under a heavy influx of webhooks by making bulk-operation state transitions race-safe, ensuring FIFO processing under backlog, and adding a “failed” terminal state for truly stuck operations.

Changes:

  • Serialize bulk-operation “check-then-act” transitions using a shared Craft mutex in nextBulkOperation() and queueNextBulkOperation(), and process the oldest queued/created-first items (FIFO) to prevent starvation.
  • Fix saveBulkOperation() so new operations without an id and without a shopifyId do not collide/overwrite existing rows.
  • Add a Failed bulk-operation status plus migration/translation coverage, and purge logic to mark long-stuck created/processing rows as failed.
File summaries
File Description
src/services/BulkOperations.php Adds mutex guarding + FIFO selection, fixes save lookup to avoid NULL collisions, and introduces purge behavior for stuck/terminal rows.
src/jobs/ProcessBulkOperationData.php Ensures after() first queues any already-created-with-URL operation before attempting to start a new queued op.
src/enums/BulkOperationStatus.php Adds Failed enum case and renders it consistently in label helpers.
src/migrations/m260908_080800_add_failed_status_to_bulk_operations.php Expands DB enum values to include failed for existing installs.
src/migrations/Install.php Ensures fresh installs include the failed status in the enum column definition.
src/Plugin.php Bumps schema version to apply the new migration.
src/translations/en/shopify.php Adds the Failed translation string used by status labels.
tests/unit/services/BulkOperationsTest.php Adds regression tests for NULL-shopifyId collisions, mutex acquisition bailouts, FIFO processing, guard query shape, and purge behavior.
tests/unit/jobs/ProcessBulkOperationDataTest.php Adds regression coverage to ensure after() unblocks stuck created ops with URLs by queueing them.
tests/unit/enums/BulkOperationStatusTest.php Ensures all enum cases have labels/colors and explicitly covers the new Failed case.
CHANGELOG.md Documents the fix, new status, and mutex constant.
Review details
  • Files reviewed: 11/11 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@nfourtythree
nfourtythree merged commit 2962cad into 7.x Sep 9, 2026
14 checks passed
@nfourtythree
nfourtythree deleted the bugfix/224-bulk-operation-deadlock branch September 9, 2026 08:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants