test(amber): restore the pgroonga global WorkflowResourceSpec clobbers - #8404
Conversation
WorkflowResourceSpec.beforeAll forces FulltextSearchQueryUtils.usePgroonga false and never puts it back. amber runs its suites serialized in one unforked JVM, so every suite scheduled after it renders the to_tsvector/to_tsquery fallback instead of production's pgroonga arm. The suite does need the false arm: its embedded Postgres has no pgroonga extension, and with the flag left true 11 of its 78 tests fail with "function pgroonga_condition(...) does not exist". So capture the live value in beforeAll immediately before the write and put exactly that back as the first statement of afterAll, rather than deleting the write. Also correct the clause in DatasetSearchQueryBuilderSpec's header comment that this change falsifies -- WorkflowResourceSpec no longer leaves the global false, so DatasetResourceSpec is the only unrestored writer left.
Automated Reviewer SuggestionsBased on the
|
There was a problem hiding this comment.
🟢 Approval recommended
The change is narrowly scoped to test hygiene, is consistent with Amber’s single-JVM test execution model, and cleanly restores the mutated global state.
Pull request overview
This PR prevents cross-suite state leakage in Amber’s test JVM by restoring the JVM-global FulltextSearchQueryUtils.usePgroonga flag after WorkflowResourceSpec runs. This keeps later suites from silently running against the fallback full-text-search path when they expect the production default.
Changes:
- Capture the pre-test value of
FulltextSearchQueryUtils.usePgroongainbeforeAllimmediately before forcing it tofalse. - Restore the captured value at the start of
afterAll(before DB teardown) to avoid leaving mutated global state behind. - Add an in-file comment documenting why the capture/restore is structured this way for unforked, single-JVM test runs.
File summaries
| File | Description |
|---|---|
| amber/src/test/scala/org/apache/texera/web/resource/dashboard/file/WorkflowResourceSpec.scala | Captures and restores the global usePgroonga flag around the suite to prevent cross-suite contamination in unforked Amber tests. |
Review details
- Files reviewed: 1/1 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
| config | throughput | MB/s | latency | max Δ latest / 7d | |
|---|---|---|---|---|---|
| 🔴 | bs=10 sw=10 sl=64 | 367 | 0.224 | 27,118/31,562/31,562 us | 🔴 +30.8% / 🔴 +109.6% |
| 🔴 | bs=100 sw=10 sl=64 | 777 | 0.474 | 126,612/159,242/159,242 us | 🔴 +12.6% / 🔴 +45.7% |
| 🔴 | bs=1000 sw=10 sl=64 | 901 | 0.55 | 1,106,051/1,235,438/1,235,438 us | 🔴 +8.5% / 🔴 +18.5% |
Baseline details
Latest main 1cbe857 from same runner
| config | metric | PR | latest main | 7d avg | Δ latest | Δ 7d |
|---|---|---|---|---|---|---|
| bs=10 sw=10 sl=64 | throughput | 367 tuples/sec | 425 tuples/sec | 755.36 tuples/sec | -13.6% | -51.4% |
| bs=10 sw=10 sl=64 | MB/s | 0.224 MB/s | 0.26 MB/s | 0.461 MB/s | -13.8% | -51.4% |
| bs=10 sw=10 sl=64 | p50 | 27,118 us | 20,727 us | 12,938 us | +30.8% | +109.6% |
| bs=10 sw=10 sl=64 | p95 | 31,562 us | 36,522 us | 15,980 us | -13.6% | +97.5% |
| bs=10 sw=10 sl=64 | p99 | 31,562 us | 36,522 us | 19,233 us | -13.6% | +64.1% |
| bs=100 sw=10 sl=64 | throughput | 777 tuples/sec | 845 tuples/sec | 976.3 tuples/sec | -8.0% | -20.4% |
| bs=100 sw=10 sl=64 | MB/s | 0.474 MB/s | 0.516 MB/s | 0.596 MB/s | -8.1% | -20.5% |
| bs=100 sw=10 sl=64 | p50 | 126,612 us | 117,808 us | 102,340 us | +7.5% | +23.7% |
| bs=100 sw=10 sl=64 | p95 | 159,242 us | 141,433 us | 109,262 us | +12.6% | +45.7% |
| bs=100 sw=10 sl=64 | p99 | 159,242 us | 141,433 us | 118,827 us | +12.6% | +34.0% |
| bs=1000 sw=10 sl=64 | throughput | 901 tuples/sec | 930 tuples/sec | 1,006 tuples/sec | -3.1% | -10.5% |
| bs=1000 sw=10 sl=64 | MB/s | 0.55 MB/s | 0.568 MB/s | 0.614 MB/s | -3.2% | -10.5% |
| bs=1000 sw=10 sl=64 | p50 | 1,106,051 us | 1,071,579 us | 999,855 us | +3.2% | +10.6% |
| bs=1000 sw=10 sl=64 | p95 | 1,235,438 us | 1,139,119 us | 1,042,833 us | +8.5% | +18.5% |
| bs=1000 sw=10 sl=64 | p99 | 1,235,438 us | 1,139,119 us | 1,070,722 us | +8.5% | +15.4% |
Raw CSV
config_idx,batch_size,schema_width,string_len,num_batches,total_ms,total_tuples,total_bytes,tuples_per_sec,mb_per_sec,lat_p50_us,lat_p95_us,lat_p99_us
0,10,10,64,20,545.17,200,128000,367,0.224,27118.12,31562.34,31562.34
1,100,10,64,20,2574.76,2000,1280000,777,0.474,126612.23,159242.31,159242.31
2,1000,10,64,20,22199.08,20000,12800000,901,0.550,1106050.63,1235438.41,1235438.41
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #8404 +/- ##
============================================
- Coverage 94.03% 94.02% -0.01%
+ Complexity 4821 4818 -3
============================================
Files 1204 1204
Lines 48991 48991
Branches 5956 5956
============================================
- Hits 46067 46063 -4
- Misses 1458 1460 +2
- Partials 1466 1468 +2
*This pull request uses carry forward flags. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…ec (apache#8403) ### What changes were proposed in this PR? `DatasetResourceSpec.beforeAll` set the JVM-global `FulltextSearchQueryUtils.usePgroonga` to `false` and never put it back. The write did nothing for this suite and everything to the suites after it. **Why it does nothing here.** `usePgroonga` is read at exactly one place in `src/main`: `FulltextSearchQueryUtils.scala:52`. That read is inside `getFullTextSearchFilter`, which is called from exactly two places in `src/main` — `VersionedResourceSearchQueryBuilder.scala:128` and `WorkflowSearchQueryBuilder.scala:120`. `DatasetResourceSpec` reaches neither with a keyword: | step | what it does | | --- | --- | | the four tests | two use only `UserDao`; two call `DatasetSearchQueryBuilder.constructQuery(uid, SearchQueryParams(resourceType = DATASET_RESOURCE_TYPE), includePublic = true)` | | `SearchQueryBuilder.constructQuery` (`final`) | `constructFromClause` + `constructWhereClause` + `mappedResourceSchema.allFields` + `getGroupByFields`; none of the first, third or fourth touches full-text (`constructFromClause` only builds jOOQ joins, `getGroupByFields` is `Seq.empty`) | | `constructWhereClause` | reaches `getFullTextSearchFilter(splitKeywords, List(DATASET.NAME, DATASET.DESCRIPTION))` | | `splitKeywords` | derived from `params.keywords`, which the tests leave at its `new util.ArrayList[String]()` default (`DashboardResource.scala:72`), so it is empty | | `getFullTextSearchFilter` | `fields` is non-empty so the `:39` guard does not fire, but `trimmedKeywords.isEmpty` returns `noCondition()` at `:46` — **before** the `:52` read | **Why it does something to everyone else.** amber has no `Test / fork` and serialises its suites in one JVM, so `false` stayed set for every suite scheduled after this one, moving their full-text rendering onto the `to_tsvector`/`to_tsquery` arm. ``` before: beforeAll: usePgroonga = false -> suite's own 4 tests: never read it -> every later suite in the JVM: reads false after: flag untouched at its production default true ``` So the write is deleted rather than captured and restored. A capture-and-restore would still leave the value wrong *during* this suite and would depend on when the suite object is constructed and on where sbt happens to schedule it; deleting the write removes the leak unconditionally. Also removed, from the same copy-paste block: - `private def getKeywordsArray`, which has no caller. After the deletion the only `getKeywordsArray` in the repository is `WorkflowResourceSpec`'s own `private` copy (definition at `:201`, 16 call sites, all in that file). Being `private`, this file's copy could only ever have been called from this file, and was not. - `import org.apache.texera.web.resource.dashboard.{FulltextSearchQueryUtils}` and `import java.util`, which were the only imports those two members needed. A short comment replaces the write, recording that the flag is left at its production default because no test here reaches the read, and what a keyword test added here would have to do instead (`MockTexeraDB` strips the full-text index block out of the DDL, so the embedded Postgres has no pgroonga extension — such a test would need the `to_tsvector` arm, and would have to put the flag back). Without it the next author copying `WorkflowResourceSpec`'s pattern re-adds the leak. **Why a second file is in the diff.** `DatasetSearchQueryBuilderSpec`'s header paragraph carried a standing instruction — every keyword assertion in that spec must stay branch-independent — and justified it by asserting this leak as fact: that `DatasetResourceSpec` and `WorkflowResourceSpec` "both set it and neither restores it", and that an assertion on `pgroonga_condition` "would pass solo and fail in a full-module run". This PR falsifies the first half for `DatasetResourceSpec` and the second half outright. The instruction is still right, so the paragraph now justifies it by the flag being JVM-global mutable state that any suite in the run may write, and states precisely which parts of a rendered predicate survive onto both arms: the `coalesce(...) || ' ' || coalesce(...)` expression (built at `FulltextSearchQueryUtils:49-51`, before the `if`, and embedded verbatim by either arm) and each individual keyword token — but *not* their joining, which the two arms render differently (test 5 below). Nothing else in that file changed — no assertion, no other comment, no reformatting. **What this PR does not do.** It does not touch `WorkflowResourceSpec`, which genuinely needs the `false` arm (it runs real keyword searches against the embedded Postgres) and still leaks it; that is a separate change, apache#8404, which restores the flag there rather than deleting the write. It does not touch `src/main` — `usePgroonga` remains a public mutable `var`. It does not add or rename a test, and it does not change any assertion anywhere. ### Any related issues, documentation, discussions? Closes apache#8399 ### How was this PR tested? Every number below was read out of `amber/target/test-reports/TEST-*.xml`, not from sbt's console summary. Local, Windows, Java 17, module `WorkflowExecutionService`. `1cbe857007` is the base commit. **1. The suite stays green.** `testOnly ...file.DatasetResourceSpec`: `tests="4" failures="0" errors="0"`. **2. The flag read is unreachable from this suite — measured, not just argued.** Temporarily armed the read site in `src/main` (`if ({ sys.error("READ REACHED"); usePgroonga })`, reverted afterwards) and ran the suite together with a control that does reach the read: | suite | XML | meaning | | --- | --- | --- | | `DatasetResourceSpec` | `tests="4" failures="0"` | none of its four tests reaches the read | | `FulltextSearchQueryUtilsSpec` | `tests="14" failures="3"` | the probe is armed; exactly its three flag-reading tests died | **3. The leak is real and the deletion removes it — same invocation, pinned order.** sbt gives separate `testOnly` invocations fresh classloaders, so the probe puts both suites in one invocation and pins their order with a `Suites` subclass that overrides `runNestedSuites` to construct each nested suite immediately before running it (sbt's own ScalaTest-framework semantics; `Suites(a, b)` would evaluate both constructors up front). | tree | printed before / after `DatasetResourceSpec` ran | observer suite | | --- | --- | --- | | `1cbe857007` | `true` / `false` | FAILURE, `false was not equal to true` | | this branch | `true` / `true` | `tests="5" failures="0"` | Control, so the observer is not vacuously red on base: run alone in its own invocation on `1cbe857007` it is `tests="1" failures="0"` — the default really is `true`, and the `false` came from `DatasetResourceSpec`. **4. The downstream arm switch, and that it turns nothing red.** Same pinned order (`DatasetResourceSpec` then `DatasetSearchQueryBuilderSpec`, one invocation), the only variable being this file: | tree | flag observed after the subject | arm that selects (test 5) | downstream result | | --- | --- | --- | --- | | `1cbe857007` | `false` | `to_tsvector`/`to_tsquery` | `tests="28" failures="0"` | | this branch | `true` | `pgroonga_condition` | `tests="28" failures="0"` | That is the point of the change — downstream suites move back onto the production arm — and it costs nothing, because those assertions are branch-independent. **5. Which parts of a rendered predicate are actually arm-independent.** A throwaway spec rendered `getFullTextSearchFilter` on both arms and dumped the SQL (`DSL.using(POSTGRES).renderInlined`, no DB needed): | keywords | `usePgroonga = true` | `usePgroonga = false` | | --- | --- | --- | | `["alpha"]` | `... &@~ pgroonga_condition('alpha', ...)` | `to_tsvector('english', ...) @@ to_tsquery('english', 'alpha')` | | `["alpha", "beta"]` | `... pgroonga_condition('alpha beta', ...)` | two predicates AND-ed, `to_tsquery('english', 'alpha')` and `... 'beta'` | | `["alpha beta"]` | `... pgroonga_condition('alpha beta', ...)` | `... @@ to_tsquery('english', 'alpha & beta')` | The `COALESCE(name, '') || ' ' || COALESCE(description, '')` expression and each individual token appear on both arms; the joined string `alpha beta` appears only on the `true` arm. Asserted as such (`tests="4" failures="0"`), which is what licenses the wording in `DatasetSearchQueryBuilderSpec`'s paragraph. And the spec's existing assertions really are arm-independent: pinning the flag to each arm and running it gives `tests="24" failures="0"` both ways. > Correction, so nobody carries the old sentence forward: an earlier revision of that paragraph (and > of this PR body) said the tokens "render identically on either arm". Review caught it and the table > above is why it was wrong — only *individual* tokens and the `coalesce` expression survive both > arms, not a joined multi-token string. The shipped paragraph now says exactly that. Nothing in the > spec asserted on a joined string, so no test changed. **6. No regression.** `AMBER_TEST_FILTER=skip-integration WorkflowExecutionService/test`, run on the base commit first and then on this branch in the same worktree. Counting `<failure>`, `<error>` and `<skipped>` children of `<testcase>` separately, because the distinction matters here: | | report files | tests | `<failure>` | `<error>` | `<skipped>` | | --- | --- | --- | --- | --- | --- | | `1cbe857007` | 195 | 2303 | 84 | 1 | 1 | | this branch | 195 | 2303 | 84 | 1 | 1 | The two non-pass identity lists are byte-identical (`diff` is empty). The 85 failures/errors are all pre-existing local-environment failures — `ResultExportServiceSpec` 17, `DataProcessingSpec` 16, `ExecutionStatsServiceSpec` 12, `ExecutionResultServiceSpec` 11, `SyncExecutionResourceSpec` 8, `InputPortMaterializationReaderThreadSpec` 8, `PveResourceSpec` 6, `ReconfigurationSpec` 2, `PauseSpec` 2, and one each in `WorkflowExecutionServiceSpec`, `GitVersionControlLocalFileStorageSpec` and `DefaultCostEstimatorSpec` (that last is a construction-time abort) — none of them in the dashboard search path this PR touches. The single `<skipped>` is `NetworkOutputBufferSpec`'s `pendingUntilFixed` test, which is not a failure at all. > Correction: an earlier revision of this body reported "86 non-pass identities" with a tail of "8 > singletons/pairs". Review could not reproduce 86 and measured 85. Both measurements were right about > the XML — 86 was 85 failures/errors plus that one `pendingUntilFixed` `<skipped>` row, silently > lumped in with the failures. The table above separates them. It was a bad count, not a flake. Worth recording, because it is why the identity diff alone is not sufficient evidence: sbt's suite order is not stable across invocations of the same command. In the base run `DatasetSearchQueryBuilderSpec` ran 1st of 195 and `DatasetResourceSpec` 54th — so the downstream spec happened to run *before* the leak and saw `true` anyway; in the branch run they were 141st and 102nd. Tests 3-5 are the ordered evidence; the module runs only show that nothing else moved. **7. Lint.** `WorkflowExecutionService/scalafmtCheck`, `WorkflowExecutionService/Test/scalafmtCheck` and `WorkflowExecutionService/scalafixAll --check` all exit 0, the last with its cache cleared so it really re-scanned both changed files (`Running scalafix on 274 Scala sources` / `on 209 Scala sources`; the one warning it prints is pre-existing, in `OutputManagerSpec`). scalafix is the gate that matters here: each deletion orphans an import. ### Was this PR authored or co-authored using generative AI tooling? Generated-by: Claude Code (Opus 5) --------- Signed-off-by: Xinyuan Lin <xinyual3@uci.edu> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
What changes were proposed in this PR?
FulltextSearchQueryUtils.usePgroonga(amber/src/main/scala/org/apache/texera/web/resource/dashboard/FulltextSearchQueryUtils.scala:32) is a JVM-globalvarwhose production default istrue. It is read at exactly one site,FulltextSearchQueryUtils.scala:52, to choose between the pgroonga arm and theto_tsvector/to_tsqueryfallback.WorkflowResourceSpec.beforeAllforces itfalseand never puts it back.amber declares no
Test / fork— the twoTest / fork := truesettings a grep finds inbuild.sbtbelong toComputingUnitManagingService(build.sbt:191) andFileService(build.sbt:227), while the amber project (WorkflowExecutionService,build.sbt:252) declares neitherforknorparallelExecution— and suites are serialized byTags.limit(Tags.Test, 1)(amber/build.sbt:48). OneWorkflowExecutionService/testrun is therefore a single JVM sharing a single flag: 193 completed suites in the run measured here.This suite genuinely needs the
falsearm, so the write is restored rather than deleted: the embedded Postgres it runs against has no pgroonga extension, and with the flag lefttrue11 of its 78 tests fail withERROR: function pgroonga_condition(unknown, fuzzy_max_distance_ratio => numeric) does not exist. The 11 are named under How was this PR tested?.The capture is taken in
beforeAll, immediately before the write, and written back as the first statement ofafterAll, ahead ofcloseConnectionPool(). That ordering is hygiene, not a fix for a live hazard:MockTexeraDB.closeConnectionPool(common/dao/src/test/scala/org/apache/texera/dao/MockTexeraDB.scala:183-192) already swallows anyExceptionitself (catch { case e: Exception => e.printStackTrace() } finally { ... }), so only anErrorcould escape it today. Putting the restore first means the ordering does not depend on that staying true.The alternative — capturing into a
valat construction time — restores whatever the flag held when sbt happened to instantiate the class, which is a property of sbt's scheduling rather than of what the suite clobbered. Both forms were run against the same scenario: an earlier suite leaves the flagfalse, then this suite runs, then a third suite reads it.private val)true— the value at instantiationtrue was not equal to falseprivate var, this PR)false— the value it clobberedHonest qualification, since it cuts against this change: that scenario is built with a nested
org.scalatest.Suites, which evaluates its nested suites as constructor arguments and therefore instantiates all of them before any of their tests run. Measured separately, sbt/ScalaTest does not do that for discovered suites — it constructs each one immediately before running it (order log:ctor:Bb, beforeAll:Bb, test:Bb, afterAll:Bb, ctor:Aa, ...). Nothing touches the flag between this suite's construction and itsbeforeAll, and there are zeroextends Suitesclasses inamber/src/test/scala, so the two forms restore the same value in a realtestrun today and are behaviourally indistinguishable there. The write-time form is preferred only because its correctness does not depend on that measurement continuing to hold: a futureTest / fork, aOneInstancePerTestmixin, or any nesting suite would each change the answer. The in-code comment carries that same qualification, so the file does not overstate the case either.The field is also initialised from the live value at its declaration. That is not decoration —
afterAllwas measured to run even whenbeforeAllthrows, so the restore can execute on a path where the capture line never did, and the initialiser keeps it from writing back an invented default.The restore is unpinned: nothing in the repo would go red if it were deleted again. Pinning the arm
falsefor an entire module run — a conservative superset of the leak's effect — leaves the failing-test identities byte-identical to baseline, so no suite inWorkflowExecutionServicecurrently reads the flag in an arm-sensitive way. This PR removes latent cross-suite state leakage; it does not fix a currently-failing test, and no fragile ordering-dependent guard suite was added to manufacture a pin.A comment elsewhere that this change falsifies.
DatasetSearchQueryBuilderSpec's header comment (:114-123) explains why that suite's keyword assertions are deliberately arm-independent, and its parenthetical names both writers of the global: "DatasetResourceSpecorWorkflowResourceSpecran earlier in this JVM and left the globalfalse(both set it and neither restores it...)". After this commit that sentence is false — this suite does restore it. This PR deliberately does not edit that comment. Any narrowing written here ("onlyDatasetResourceSpecleaks") would itself become false the moment the sibling PR lands, so the correction belongs in exactly one place: the sibling (#8403) rewrites that paragraph into a form that names no suite at all and is therefore true whichever of the two merges first. If this PR merges first, the comment is stale until the sibling lands — and the guardrail it states, "anything added here must keep that property", stays valid in every one of the four states, so nothing that reads it is misled about what to do.Writers of the global today:
FulltextSearchQueryUtilsSpec:64,71,87after { ... }, per testWorkflowResourceSpec:179DatasetResourceSpec:99Once both land, this spec is the only writer of the global outside
FulltextSearchQueryUtilsSpec. With only one of the two applied the flag's end state differs — with only this PR,DatasetResourceSpecstill writesfalsewithout restoring; with only the sibling, this suite still leaksfalse— and whichever of the two sbt schedules last decides it (sbt's order was measured to be neither alphabetical nor command-line order). Inference, not a measurement: since nothing in the module was found to be arm-sensitive, the failing-test identity set should not move in either partial state. The sibling-only tree was never built or run, so that half is reasoning from the arm-sensitivity measurement rather than an observation.Scope. One test file, +17 lines: the capture, the restore, and the comment explaining why the capture sits where it does. No
src/mainfile is touched and no other test file is touched. No test is added, renamed or deleted; the suite's own 78 tests are unchanged and so are their outcomes.Any related issues, documentation, discussions?
Closes #8400
How was this PR tested?
Everything below is read out of
amber/target/test-reports/TEST-*.xml, not the sbt console summary. All probe suites were deleted before committing; the branch is one commit.1. The suite really does need the
falsewrite. WithbeforeAllchanged to leave the flagtrue,WorkflowResourceSpecalone reports 78 tests and 11 failures, every one anorg.jooq.exception.DataAccessExceptioncaused byERROR: function pgroonga_condition(unknown, fuzzy_max_distance_ratio => numeric) does not exist. The suite passes keywords through agetKeywordsArrayhelper at 16 call sites (:331-751), one of them with the reserved-character string"+-@()<>~*\"", so it reaches the flag read for real instead of taking the empty-keywords early return atFulltextSearchQueryUtils.scala:45-47.So the right fix here is a restore, not the deletion the sibling PR makes.
2. Red before / green after, with an explicitly-ordered throwaway probe —
Suites(new WorkflowResourceSpec, new PgroongaProbeTailSpec), where the tail asserts the global still holds production's default. The nesting pins the ordering because a plaintestOnlyof two classes does not order them. Both suites in the same invocation, since separate invocations get fresh classloaders and reset the static:1cbe857007the JVM-global usePgroonga, after the preceding suite finished should still hold production's defaultThe control matters: the tail assertion is not unconditionally red, so its red above is caused by the leak.
3. Write-time vs construction-time capture — the table in the first section. Same probe shape, with an added first nested suite that leaves the flag
false. Both arms were measured on the committed content: the write-time arm as committed, the construction-time arm by changing onlyvartovaland dropping the capture line frombeforeAll. The construction-time form restorestrueand clobbers it (XML:true was not equal to falseonusePgroonga after WorkflowResourceSpec should still be the false the earlier suite left); the write-time form restoresfalseand the run is 80/80. As stated above, this reflects the eager instantiation thatSuitesnesting creates rather than sbt's own (measured lazy) behaviour, so it is a design argument, not a live bug.4. Instantiation and lifecycle semantics, measured with an append-only order log from two suites plus one whose
beforeAllthrows:Four findings: construction is lazy, per suite, immediately before that suite runs; suites do not interleave;
afterAllstill runs whenbeforeAllthrows (sbt reportedSuites: completed 2, aborted 1and the throwing suite's test never logged a line, so the restore can execute on a path where the capture never did); andBbran beforeAaalthoughAawas listed first on thetestOnlycommand line and sorts first alphabetically.5. Arm sensitivity, i.e. why the restore is unpinned. Production default mutated
true->falseinsrc/mainfor one whole module run, then reverted: 195 report files and 86 non-passing identities, byte-identical to the baseline list (diffempty). That is a superset of the leak's effect — every one of the 193 suites ran on the fallback arm, not just the ones scheduled after this spec — so no suite outcome in this module depends on the arm. The mutation was reverted and verified:git diff --name-only 1cbe857007 -- '*/src/main/*'is empty and line 32 readsvar usePgroonga: Boolean = trueagain.6. Regression, widest scope that runs locally —
AMBER_TEST_FILTER=skip-integration sbt WorkflowExecutionService/test, baseline (both touched files at their1cbe857007content) measured first. Counting rule: a non-passing identity is a<testcase>element inamber/target/test-reports/TEST-*.xmlcarrying a<failure>,<error>or<skipped>child, printed asKIND \t suite \t test nameand sorted; the same rule is applied to both runs.1cbe857007diffof the two sorted identity lists is empty. The 86 break down as 84<failure>+ 1<error>(the aborted suite'sSuiteSelectorpseudo-testcase) + 1<skipped>, and the run's own reporter tally agrees:Total 2301, Failed 84, Errors 1, Passed 2216, Canceled 1, Pending 1. Excluding<skipped>the same runs read as 85 rows — the absolute number is method-dependent, which is why the rule is stated; the load-bearing fact is that the two lists are byte-identical, not the count.All 86 are pre-existing on this box, in 13 suites, none of them touched by this PR:
org.apache.iceberg.exceptions.RESTException— REST catalog GET tolocalhost:8181, no Docker on this boxjava.lang.ThrowablePython executable not found for PVERESTExceptionfrom the same catalog GET at constructiontestFileTreeRetrieval<skipped>row — apendingUntilFixedtest, not a failureWorkflowResourceSpec, the only file this PR touches, is green in both wide runs attests="78" errors="0" failures="0"; so isDatasetSearchQueryBuilderSpec(tests="24"), the spec whose header comment describes this leak. The change alters what the suite leaves behind, not what it asserts.7. Lint (CI gates):
WorkflowExecutionService/scalafmtCheck,WorkflowExecutionService/Test/scalafmtCheckandWorkflowExecutionService/scalafixAll --checkall report[success]on the committed tree.Corrections made after review. Four claims in an earlier draft of this description were wrong or unstated, and are corrected above rather than quietly dropped: (a) the restore-before-teardown ordering was justified as protecting against a teardown throw, but
closeConnectionPoolcatchesExceptionitself, so the justification is hygiene only; (b) the non-passing identity count is counting-method dependent (the same runs read as 85 rows if<skipped>is excluded), so the rule is now stated; (c) the pre-existing local failures were described as Iceberg/Docker dashboard suites, which under-describes them — see the table above; and (d) this PR falsifies a sentence inDatasetSearchQueryBuilderSpec's header comment, which the earlier draft cited as supporting evidence without disclosing that it goes stale; An earlier revision of this branch corrected that comment here; the edit has been reverted, because the narrowing it wrote would go false as soon as the sibling landed. The correction now lives only in the sibling PR, in an order-neutral form, and this PR discloses the staleness instead.Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Opus 5)