Skip to content

[Improvement] Refactor IndexQueueRepository to use named column aliases and simplify deleteQueueEntries#409

Merged
mcop1 merged 7 commits into2026.xfrom
improvement/refactor-index-queue-named-aliases
Mar 31, 2026
Merged

[Improvement] Refactor IndexQueueRepository to use named column aliases and simplify deleteQueueEntries#409
mcop1 merged 7 commits into2026.xfrom
improvement/refactor-index-queue-named-aliases

Conversation

@mcop1
Copy link
Copy Markdown
Contributor

@mcop1 mcop1 commented Mar 30, 2026

Summary

  • Refactors generateSelectQuery to accept an associative columnAliases array (alias => expression) instead of positional $selects, producing named SQL aliases (e.g. id AS elementId) for robust, position-independent result extraction
  • Refactors getValuesFromSqlResult to extract values by column alias name instead of fragile positional index access
  • Updates all EnqueueService callers and type adapters (Asset, Document, DataObject) to use the new associative alias format
  • Cleans up deleteQueueEntries: improved code structure and quoting while preserving the (id, operationTime) tuple matching that guards against race conditions
  • Removes the unused quoteParameters method
  • Adds 11 unit tests covering generateSelectQuery, enqueueBySelectQuery, and deleteQueueEntries

Motivation

The previous implementation used positional array indices ($result[0], $result[1], etc.) to extract values from SQL query results. This was fragile — any change to column order in the SELECT statement would silently break the mapping. Named column aliases make the code self-documenting and resilient to column reordering.

deleteQueueEntries — operationTime guard

The deleteQueueEntries method matches on WHERE (id, operationTime) IN (...) rather than just WHERE id IN (...). This is intentional — it acts as an optimistic-concurrency guard:

  1. The queue table has a unique index on (elementId, elementType), so only one queue entry per element can exist
  2. Re-queueing (e.g., element saved again during processing) uses ON DUPLICATE KEY UPDATE, which updates the existing row in-place — same id, but new operationTime
  3. If deleteQueueEntries matched only on id, it would delete the re-queued entry, losing the pending update
  4. By matching on (id, operationTime), the DELETE becomes a no-op when operationTime has changed, and the re-queued entry survives for the next processing cycle

Two dedicated unit tests document and verify this behavior.

…es and simplify deleteQueueEntries

- Refactor generateSelectQuery to accept associative columnAliases array (alias => column) instead of positional selects, producing named SQL aliases
- Refactor getValuesFromSqlResult to extract values by column alias name instead of fragile positional index access
- Update all EnqueueService callers and type adapters to use new associative alias format
- Simplify deleteQueueEntries to use WHERE id IN (...) leveraging the primary key
- Remove unused quoteParameters method
- Add unit tests for generateSelectQuery and enqueueBySelectQuery
@mcop1 mcop1 self-assigned this Mar 30, 2026
@mcop1 mcop1 added this to the 2026.1.0 milestone Mar 30, 2026
The simplified WHERE id IN (...) introduced a race condition: if an element
is re-queued (via ON DUPLICATE KEY UPDATE) while being processed, the
operationTime on the existing row changes but the id stays the same. The
id-only DELETE would accidentally remove the re-queued entry, losing the
pending update.

Restore the original WHERE (id, operationTime) IN (...) tuple matching.
This acts as an optimistic-concurrency guard: if operationTime changed
since the entry was fetched, the DELETE is a no-op and the re-queued
entry survives for the next processing cycle.

Add unit tests documenting this race condition protection.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Refactors IndexQueueRepository and related enqueue/query-building code to use named SQL column aliases (instead of positional extraction) when selecting items to enqueue into the index queue, and updates tests accordingly.

Changes:

  • Refactored generateSelectQuery() to accept an associative alias-to-expression map and updated call sites to produce named aliases.
  • Refactored result extraction in enqueueBySelectQuery() to read values by alias names instead of positional indexes.
  • Added new unit tests for generateSelectQuery(), enqueueBySelectQuery(), and documented deleteQueueEntries() behavior with operationTime guarding.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/Repository/IndexQueueRepository.php Implements alias-based select generation and alias-based result extraction; refactors delete query construction and removes unused quoting helper.
src/Service/SearchIndex/IndexQueue/EnqueueService.php Updates enqueue queries to provide the new alias map to generateSelectQuery().
src/Service/SearchIndex/IndexService/ElementTypeAdapter/AssetTypeAdapter.php Adds explicit AS <alias> names to the select list for related-item enqueue queries.
src/Service/SearchIndex/IndexService/ElementTypeAdapter/DocumentTypeAdapter.php Adds explicit AS <alias> names to the select list for related-item enqueue queries.
src/Service/SearchIndex/IndexService/ElementTypeAdapter/DataObjectTypeAdapter.php Adds explicit AS <alias> names to the select list for related-item enqueue queries and derived select parameters.
tests/Functional/SearchIndex/IndexQueueTest.php Updates functional test to call generateSelectQuery() with alias map.
tests/Unit/Repository/IndexQueueRepositoryTest.php Adds unit tests covering named aliases, where parameters, empty results, and delete guarding behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

mcop1 added 4 commits March 31, 2026 09:31
Add InvalidArgumentException when generateSelectQuery() receives numeric
keys in $columnAliases, catching misuse from callers migrating from the
old positional array API.

Update upgrade notes: mark generateSelectQuery() change as BC break,
remove private getValuesFromSqlResult() entry (not relevant for upgrades).
@sonarqubecloud
Copy link
Copy Markdown

@mcop1 mcop1 merged commit e6d91be into 2026.x Mar 31, 2026
11 checks passed
@mcop1 mcop1 deleted the improvement/refactor-index-queue-named-aliases branch March 31, 2026 07:58
@github-actions github-actions bot locked and limited conversation to collaborators Mar 31, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants