Skip to content

Make updateSiblings and resetChildrenIndexBy fully async#426

Open
cancan101 wants to merge 5 commits into
pimcore:2026.xfrom
cancan101:claude/github-issue-389-fOm4d
Open

Make updateSiblings and resetChildrenIndexBy fully async#426
cancan101 wants to merge 5 commits into
pimcore:2026.xfrom
cancan101:claude/github-issue-389-fOm4d

Conversation

@cancan101

Copy link
Copy Markdown
Contributor

Changes in this pull request

Resolves #389

Additional info

  • DataObjectIndexUpdateSubscriber::updateDataObject() and DocumentIndexUpdateSubscriber::updateDocument() were calling IndexElementIndexService::updateSiblings() and resetChildrenIndexBy() synchronously, making blocking calls to the search provider (e.g. OpenSearch/Elasticsearch) during HTTP requests
  • Introduced UpdateSiblingsMessage and UpdateSiblingsHandler to dispatch sibling/children index updates via the Symfony Messenger bus, so they are processed asynchronously through the existing pimcore_generic_data_index_queue transport
  • Removed the direct IndexElementIndexServiceInterface dependency from both event subscribers, replacing it with MessageBusInterface to dispatch the new message

This eliminates the synchronous search-provider roundtrips that caused significant slowdowns during object updates, especially for large folders.

Test plan

  • Verify data object updates dispatch UpdateSiblingsMessage to the queue instead of blocking
  • Verify document updates dispatch UpdateSiblingsMessage to the queue instead of blocking
  • Verify sibling index values are correctly updated after async processing
  • Verify resetChildrenIndexBy is triggered for data objects with OBJECT_CHILDREN_SORT_BY_INDEX sort mode
  • Verify no regressions in add/delete operations (unchanged paths)
  • Confirm message routing via config/pimcore/messenger.yaml

cancan101 added 2 commits May 25, 2026 15:49
The updateDataObject and updateDocument event subscribers were calling
IndexElementIndexService::updateSiblings() and resetChildrenIndexBy()
synchronously, which made blocking calls to the search provider during
HTTP requests. This caused significant slowdowns for large folders.

Dispatch an UpdateSiblingsMessage via the message bus so that sibling
and children index updates are processed asynchronously through the
existing queue infrastructure, consistent with how updateData() works.
Tests cover:
- UpdateSiblingsHandler: verifies service method dispatch based on
  element type, sort-by-index flag, resetChildrenIndexBy flag, and
  null element handling
- DataObjectIndexUpdateSubscriber: verifies UpdateSiblingsMessage is
  dispatched with correct parameters
- DocumentIndexUpdateSubscriber: same verification for documents
@sonarqubecloud

Copy link
Copy Markdown

@cancan101

Copy link
Copy Markdown
Contributor Author

Follow up PR: cancan101#2

@mcop1 mcop1 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.

Hello @cancan101 ,
thanks for the pr, could you merge the current 2026.x again? This should fix the failing tests.

I noticed a few things:

  • resetChildrenIndexBy() fills the shared BulkOperationService buffer but never
    calls commit() (unlike updateSiblings(), see IndexElementIndexService.php:77).
  • I guess we need to consult SynchronousProcessingServiceInterface as well here, because CLI and tests enable synchronous mode and expect direct results
  • UpdateSiblingsMessage gets dispatched on every save, ignoring the isInstalled guard in updateData

How do you want to handle the follow up? Merge this pr first, then rebase the follow up to 2026.x in pimcore/gdi?

if ($event->getObject()->getChildrenSortBy() === AbstractObject::OBJECT_CHILDREN_SORT_BY_INDEX) {
$this->indexElementIndexService->resetChildrenIndexBy($event->getObject());
}
$this->messageBus->dispatch(

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.

Move the isInstalled guard up here? Or at least check it here as well?

&& $element instanceof AbstractObject
&& $element->getChildrenSortBy() === AbstractObject::OBJECT_CHILDREN_SORT_BY_INDEX
) {
$this->indexElementIndexService->resetChildrenIndexBy($element);

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.

commit() missing here, either add it to message, or probably even at the end of resetChildrenIndexBy method itself.

claude added 3 commits July 9, 2026 22:39
- Commit the bulk buffer at the end of resetChildrenIndexBy() so children
  index resets are actually flushed to the search index (previously the
  buffer was filled via addUpdate() but never committed).
- Respect synchronous processing in the update subscribers: dispatch
  UpdateSiblingsMessage with a SYNC TransportNamesStamp when
  SynchronousProcessingService is enabled, so CLI commands and tests get
  direct, synchronous results (mirrors QueueMessagesDispatcher).
- Guard the message dispatch behind Installer::isInstalled() in
  updateDataObject()/updateDocument() so no message is dispatched when the
  bundle is not installed, matching the existing guard in updateData().
- Extend the subscriber unit tests to cover the synchronous-dispatch and
  not-installed paths.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017t757oNTEGGJYPTdnTaMsA
@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

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.

updateDataObject is only partially async

5 participants