Skip to content

Add Oak query-index detection for Groovy scripts - #85

Merged
royteeuwen merged 4 commits into
mainfrom
feature/query-index-detection
Jul 19, 2026
Merged

Add Oak query-index detection for Groovy scripts#85
royteeuwen merged 4 commits into
mainfrom
feature/query-index-detection

Conversation

@royteeuwen

@royteeuwen royteeuwen commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

What

Detect whether the JCR queries a Groovy Console script runs are backed by an Oak index, so a project can verify the indexes its migration/report scripts rely on actually exist — before shipping.

Query-audit extension (extensions/query-audit)

A single optional OSGi bundle (no content package, not in the core all package):

  • POST /bin/groovyconsole/query-audit with a script or scriptPath — same permission model as script execution. Runs the script, captures the statements Oak executes, EXPLAINs each against the live repository, and returns JSON:
    { "output": "", "exceptionStackTrace": "",
      "queries": [ { "statement": "", "plan": "", "needsIndex": true } ] }
    needsIndex=true means Oak had to traverse — no index on this instance covers that query.
  • Mirrors AEM's Explain Query tool: a logback collector over the Oak query + Day QueryBuilder loggers, isolated per request via an MDC marker. Pure Java; logback is provided/optional so the core console stays logback-free and Cloud-safe.
  • Query audit panel in the modern console (a ConsoleUiExtensionProvider + a servlet serving a self-contained ES module from the bundle): audits the script currently in the editor and shows the per-query index report — no pasting.

Modern console extension API

Adds window.GroovyConsole.getScript() so a UI extension can read the editor's active script (the shell provides it via setActiveScriptProvider). Small, general addition alongside the existing registerPanel / gc-set-script / gc-toast contract.

Optional migration integration

A migration run started with measureIndexUsage=true measures each script's index usage via the (optional) QueryAuditService and reports per-script findings — useful for validating migrations in CI. No hard dependency: the reference is optional/dynamic, so the migration extension works with or without the query-audit extension installed (e.g. on AEM as a Cloud Service, where it's simply skipped).

Unit-test index audit (ui.content)

IndexAudit runs a script against real in-memory Oak (JCR_OAK) and reports the plan per query, so a unit test can list the indexes a script needs and verify coverage once a definition is installed (property indexes; Lucene needs a live instance).

Live ITs (it.tests)

IndexDetectionIT and MigrationIndexAuditIT validate the servlet and the migration integration against the running instance's real Oak indexes.

Notes

  • No changes to the core console runtime beyond the small getScript() extension-API addition; the extension and the migration hook are entirely opt-in.
  • Exploratory material (design docs, the raw-Oak spike, the sling-mock-oak Lucene contribution patch) is intentionally kept out of this PR.

Testing

mvn test -pl bundle,extensions/migration/bundle,ui.content green (11 / 31 / 15); ui.frontend tsc + unit tests green. mvn clean install -Pit -Dit.test=IndexDetectionIT,MigrationIndexAuditIT green against a live Sling instance.

@royteeuwen
royteeuwen force-pushed the feature/query-index-detection branch 5 times, most recently from 5e96483 to 9da0580 Compare July 8, 2026 18:58
Detect whether the JCR queries a Groovy Console script runs are backed by an
Oak index, so a project can verify the indexes its migration/report scripts
rely on actually exist.

Query-audit extension (extensions/query-audit) — a single optional OSGi bundle,
no content package:
- QueryAuditServlet: POST /bin/groovyconsole/query-audit with a script or
  scriptPath; same permission model as script execution. Returns JSON
  {output, exceptionStackTrace, queries:[{statement, plan, needsIndex}]}.
- QueryPlanAuditor (implements the QueryAuditService SPI): runs the script via
  GroovyConsoleService while capturing the statements Oak executes (logback
  ListAppender on the oak query + Day QueryBuilder loggers, isolated per thread
  via an MDC marker), then EXPLAINs each. Mirrors AEM's Explain Query tool.
  Pure Java; logback is provided/optional so the core console stays logback-free
  and Cloud-safe.
- Query audit panel in the modern console: a ConsoleUiExtensionProvider plus a
  servlet serving a self-contained ES module (kept in the bundle, no content
  package). The panel audits the script currently in the editor — no pasting.

Modern console extension API: add window.GroovyConsole.getScript() so a panel
can read the editor's active script (the shell provides it via
setActiveScriptProvider).

Optional migration integration — a migration run started with
measureIndexUsage=true measures each script's index usage via the (optional)
QueryAuditService and reports per-script findings, for CI validation. No hard
dependency: the reference is optional/dynamic, so migration works with or
without the query-audit extension (e.g. on AEM as a Cloud Service).

Unit-test index audit (ui.content): IndexAudit runs a script against real Oak
(JCR_OAK) and reports the plan per query, so a unit test can list the indexes a
script needs and verify coverage (property indexes; Lucene needs a live
instance). Live ITs (IndexDetectionIT, MigrationIndexAuditIT) validate the
servlet and the migration integration against the running instance.
@royteeuwen
royteeuwen force-pushed the feature/query-index-detection branch from 9da0580 to de9f031 Compare July 8, 2026 19:48
Replace the query-audit drawer panel with a split Run button ("Run with
query audit") and a "Query audit" tab in the output dock. The console
gains two generic UI extension hooks - GroovyConsole.registerRunAction
and registerRunResultTab - so extensions plug into the run flow without
the console knowing them.

The audit servlet passes result/runningTime through so an audited run
behaves like a normal one, and AuditedQuery now reports the query
language, with converted XPath queries mapped back to their original
statement. Adds the AuditQueryIndexes sample script (indexed uuid
lookup vs un-indexed property filters in JCR-SQL2 and XPath).
…etection

# Conflicts:
#	extensions/migration/bundle/src/main/groovy/be/orbinson/aem/groovy/console/migration/impl/DefaultMigrationService.groovy
#	ui.frontend/src/components/gc-app-bar.ts
#	ui.frontend/src/components/gc-app.ts
#	ui.frontend/src/styles/app.css
@sonarqubecloud

Copy link
Copy Markdown

@royteeuwen
royteeuwen merged commit 512028a into main Jul 19, 2026
3 checks passed
@royteeuwen
royteeuwen deleted the feature/query-index-detection branch July 19, 2026 20:26
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.

1 participant