Issue #3586315: Avoid full catalog scan when agent has no scope subscriptions.
Description
AiContextSelector::getPrefilteredPublishedItemIds() returned NULL when $scopeSubscriptions was empty, causing the chunk loop to fall back to a full catalog scan on every AI request.
For SELECTION_MODE_MINIMAL with no subscriptions, only global items and target-entity auto-included items can ever be selected. Subscription-scoped items are always discarded during scoring, so loading every published context item is unnecessary. On sites with many context items, this results in dozens of extra chunked queries per request, affecting the common "global items only" agent configuration.
This MR replaces the full scan with a targeted prefilter when using SELECTION_MODE_MINIMAL with no subscriptions.
The prefilter includes:
- Global items — retrieved directly from the scope index (
scope_id = 'global'). - Unindexed items — items without any scope index entries. These contain only non-indexed scopes (such as
target_entity, stored separately via a DER field) or no scopes at all, making them a safe superset of target-entity-only candidates. - Current target-entity items — items that explicitly reference the current target entity via the DER field. This also covers the edge case where an item has both a subscription scope (indexed) and a target entity reference.
SELECTION_MODE_MATCH_ALL is unchanged and continues to scan the full catalog.
Files changed
-
AiContextScopeIndexService
- Added
getIndexedItemIds()to return which IDs have at least one scope index entry.
- Added
-
AiContextScopeResolver
- Added
getUnindexedItemIds()to return IDs that are absent from the scope index.
- Added
-
AiContextSelector
- Added
buildNoSubscriptionCandidateIds()andloadTargetEntityCandidateIds(). - Updated
getPrefilteredPublishedItemIds()to accept$selectionModeand apply the targeted prefilter forSELECTION_MODE_MINIMALwhen no subscriptions are present.
- Added
-
AiContextSelectorNoSubscriptionPrefilterTest
-
Added a kernel test covering:
- global selection
MATCH_ALLbehaviorneverIncludealwaysInclude- no-subscription behavior
-
Testing instructions
-
Enable the module and create several context items:
- at least one with Global scope
- one or more with a non-global scope (for example, Language or Tag)
-
Create an agent at
/admin/config/ai/agentsand leave its scope subscriptions empty. -
Enable debug logging at Configuration → AI Context → Settings → General → Enable debug logging.
-
Trigger an AI request using that agent (for example, through the AI Agents Debugger).
-
Open the Drupal log (
/admin/reports/dblog) and verify a message similar to:AiContextSelector: no-subscription prefilter selected X of Y published item IDswhere X is significantly smaller than Y (only global and unindexed candidates are selected rather than the full catalog).
-
Verify that the agent response still includes the global context item.
-
Repeat the test with an agent that has scope subscriptions and verify behavior remains unchanged.
Checklist
- I have updated the MR title to use format:
Issue #1234: My issue title. - I have updated the MR description to include:
Closes #1234 - I have performed a self-review of my own code
- I have added or updated tests, or explained in the description why this change is not covered by tests
- I have updated documentation for any new or changed functionality
- I have written testing instructions and verified them locally
- I have noted any required post-merge steps (config imports, cache rebuilds, manual changes)
- This MR contains no breaking API or hook changes, or they are explicitly documented in the description
AI Compliance
Note
Check the one that best describes your usage, or leave all unchecked if AI was not significantly used.
-
AI Assisted Code
Mainly written by a human; AI used for autocomplete or partial generation under full human supervision. -
AI Generated Code
Mainly generated by AI, reviewed and approved by a human before this MR was created. -
Vibe Coded
Generated by AI and only functionally reviewed before this MR was created.
Closes #3586315