Designing a Safe Magento Admin Reindex Queue
How Admin Reindex uses Magento queues, bulk operations, ACL, locking, worker-health signals, progress ownership, and failure isolation.
The problem is not adding an Admin action
Magento already exposes indexer state in System > Tools > Index Management. The missing operational step is a safe way for an authorised administrator to request selected reindex or reset work without holding an HTTP request open or requiring shell access.
A synchronous controller is attractive because it is small, but it couples page lifetime, PHP limits and browser behaviour to work that may take minutes. It also becomes difficult to explain what happens when two administrators choose the same indexer, one indexer fails, or no consumer is running. The queue design has to answer those questions before the button is useful.
- The Admin request should validate and schedule, not perform full reindex work.
- Permissions must be narrower than general Index Management access.
- The same indexer must not be queued twice while equivalent work is open.
- A failure for one indexer must not hide the state of the remaining selection.
Use Magento-owned primitives for each responsibility
The implementation uses Magento Bulk Operations to represent user-visible work, Message Queue to execute it outside the request, ACL to authorize the action, LockManager to protect scheduling, cron history and the consumer lock as health signals, and native indexer APIs for Reindex and Reset.
That division matters. The module does not introduce a second job table, a custom process supervisor or a parallel indexer abstraction. Magento remains responsible for indexer state and message consumption, while the extension contributes request validation, operation ownership, deduplication and progress presentation.
[Admin user]
| ACL + selection validation
v
[Scheduler lock] --> [Open-operation dedupe]
| new work | existing work
v v
[Bulk operation] --------> [Progress aggregation]
|
v
[Message queue] --> [Consumer] --> [Native indexer API]
|
v
[Status + Magento logs]Make scheduling idempotent under concurrency
A read-then-publish check is not enough. Two Admin requests can both observe no open operation and publish the same indexer before either request writes the state the other one expects. The duplicate check and publish decision therefore run inside one Magento LockManager lock.
For a mixed selection, the scheduler can reuse existing bulk UUIDs for indexers already pending or running and create a new bulk only for the remaining indexers. The progress view aggregates those UUIDs so the administrator still sees each selected indexer once.
return $lockManager->lock($lockName, 0)
? $this->scheduleInsideLock($adminUserId, $selectedIndexerIds)
: $this->reuseOpenOperations($adminUserId, $selectedIndexerIds);Treat worker health as evidence, not a promise
A queued operation is not the same as a running operation. The Admin should warn before scheduling when there is no evidence that the configured consumer path is working. Useful signals include Magento's consumer lock, recent successful or running consumers_runner cron history, the age of pending module operations, and the last operation start time.
No single signal is perfect. A continuously running consumer started without the expected lock option may be healthy while idle but invisible to the lock check. Recent successful processing can still count as evidence. The warning should describe uncertainty, allow an intentional queue, and never start an operating-system process from the Admin request.
Keep progress scoped and failures isolated
Bulk progress is restricted to the administrator who created the work. That prevents an otherwise authorised user from reading another administrator's operation detail merely by learning a UUID. The UI receives safe summaries, while full exceptions remain in Magento logs with the indexer identifier and operation context.
The consumer processes selected indexers so one failure can be recorded without discarding later work. A complete, running, skipped, failed and remaining count is more useful than a single percentage because it explains partial success and makes support diagnosis possible.
- Validate the requested indexer IDs against Magento's indexer collection.
- Record ownership when the bulk is created and enforce it when progress is read.
- Log the complete exception server-side and return a non-sensitive Admin summary.
- Do not mark the whole selection successful when one child operation failed.
Failure modes to test before release
The happy path proves very little for background work. The release matrix should include an absent consumer, two near-simultaneous requests for the same indexer, a mixed selection with existing work, an indexer that throws, a user without the dedicated ACL, a user trying to read another owner's progress, and a page closed immediately after scheduling.
Installation also matters. The queue destination is registered through Magento setup, so skipping setup:upgrade can leave a request that appears scheduled but never reaches a valid consumer path.
composer require haroone/module-admin-reindex:^1.0
php bin/magento module:enable Haroone_AdminReindex
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento cache:cleanVerification checklist
Verify the request, queue, consumer, Magento indexer state and visible Admin result as one workflow. A green controller response is not enough.
- Confirm an authorised user can schedule Reindex and Reset for selected rows.
- Confirm an unauthorised role cannot see or invoke the actions.
- Confirm duplicate requests reuse open work rather than publishing another message.
- Stop the consumer and confirm the warning and queued state are understandable.
- Start the consumer and confirm queued work progresses without reopening the page.
- Force one indexer failure and confirm later work continues and the full error reaches logs.
Continue with related work
Apply this to the store you are operating.
Share the Magento version, affected path, constraints and current evidence. The quote flow keeps this article as the source context.