Skip to content

test(amber): add no-DB specs for the dashboard search query tier - #7116

Open
aglinxinyuan wants to merge 1 commit into
apache:mainfrom
aglinxinyuan:test-dashboard-query
Open

test(amber): add no-DB specs for the dashboard search query tier#7116
aglinxinyuan wants to merge 1 commit into
apache:mainfrom
aglinxinyuan:test-dashboard-query

Conversation

@aglinxinyuan

Copy link
Copy Markdown
Contributor

What changes were proposed in this PR?

FulltextSearchQueryUtilsSpec was the only spec in the dashboard package. It also proves the approach: a dialect-only DSL.using(SQLDialect.POSTGRES) context renders jOOQ parts with no connection, and ctx.newRecord(...) builds records purely in memory. These three specs extend that to the rest of the connection-free tier.

New spec Target Why it isn't DB-bound
DashboardResourceSpec getOrderFields, unknown-resourceType guard both public and pure; the guard throws before any query is built
WorkflowSearchQueryBuilderSpec toEntryImpl, mappedResourceSchema this object drops the trait's protected, widening access to public
UnifiedResourceSchemaSpec apply, the translatedFieldSet de-dup 24 default-arg Fields, all DSL.inline/cast/castNull

getOrderFields — existing coverage was only incidental (via WorkflowResourceSpec) and reached NameAsc/Desc, ExecutionTimeAsc/Desc, and EditTime through the default. This adds CreateTime both ways and the non-matching fall-through. It also pins the asc/desc asymmetry:

Asc  -> "resourceCreationTime" asc
Desc -> "resourceCreationTime" desc nulls last

That asymmetry is the point: Postgres defaults to NULLS LAST for ASC and NULLS FIRST for DESC, so the explicit nullsLast() on the descending branch is what makes the observable ordering symmetric. Dropping it looks like a harmless simplification and silently moves NULLs to the top of every descending page.

toEntryImpl — covers the projects-aggregate lookup, both comma-split branches, the NULL-privilege fallback to NONE, and the ownership flag both ways. The first test deliberately pins the aggregate lookup itself: toEntryImpl builds a fresh groupConcatDistinct(WORKFLOW_OF_PROJECT.PID) rather than reusing the one in mappedResourceSchema, so the whole projects feature rides on jOOQ comparing two structurally identical aggregates as equal.

UnifiedResourceSchema — the counts were measured, not assumed: 24 aliases, collapsing to 6 entries for the all-defaults schema and 17 for the workflow schema.

Assertion strength was checked by mutating production and confirming red, then reverting (git diff -- amber/src/main is empty):

Mutation Caught by
desc().nullsLast()desc() 2 tests
EditTimeresourceCreationTimeField 2 tests
into(WORKFLOW_OF_USER).getUid == uidinto(USER).getUid != uid 2 tests
privilege fallback NONEREAD 1 test
de-dup guard → if (true) 3 tests

Out of scope, and noted in-file: translateRecord, resultsOwnersInfo, searchAllPublicResourceCall, constructQuery and every fetch path go through SqlServer.getInstance().createDSLContext(). DatasetSearchQueryBuilder is untouched — all five of its members are override protected, and Scala protected grants no same-package access.

Two things deliberately not asserted, with the reasoning left in the files: case None => List() in getOrderFields and case _ => null in the private getColumnField are unreachable (the regex yields only four column names, all mapping non-null); and the projects parser's NumberFormatException on a padded separator is real but unproducible in production, so pinning it would only punish someone hardening the parser.

None of these specs reads or writes FulltextSearchQueryUtils.usePgroonga, so they neither depend on it nor mutate it — worth stating because two existing specs set that JVM-global and never restore it while amber's suites run concurrently.

Fragilities found in passing, reported rather than changed: DashboardWorkflow.ownerId is read as record.into(USER).getUid although the projection never selects USER.UID — it works only because jOOQ matches the unqualified name uid against workflow_of_user.uid; and searchAllResources's per-record resourceType match has no default arm, so changing the inline 'workflow' literal becomes a runtime MatchError.

Any related issues, documentation, discussions?

Closes #7115

How was this PR tested?

Three new specs, 27 tests. Run together with the existing sibling spec to confirm nothing in the package regressed — 41 tests, Java 17:

sbt "WorkflowExecutionService/testOnly org.apache.texera.web.resource.dashboard.DashboardResourceSpec org.apache.texera.web.resource.dashboard.WorkflowSearchQueryBuilderSpec org.apache.texera.web.resource.dashboard.UnifiedResourceSchemaSpec org.apache.texera.web.resource.dashboard.FulltextSearchQueryUtilsSpec"
[info] Suites: completed 4, aborted 0
[info] Tests: succeeded 41, failed 0, canceled 0, ignored 0, pending 0
[info] All tests passed.

Verified with no Postgres provisioned locally, which is the point. Test/scalafmtCheck and Test/scalafix --check both [success].

One brittleness to be aware of: the expected strings (desc nulls last, cast(null as timestamp), 'workflow' as "resourceType") and the de-dup counts are jOOQ 3.19.36 rendering artifacts, so a jOOQ bump could require updating them together.

Was this PR authored or co-authored using generative AI tooling?

Generated-by: Claude Code (Opus 5)

FulltextSearchQueryUtilsSpec was the only spec in the dashboard package. It
also proves the approach: a dialect-only `DSL.using(SQLDialect.POSTGRES)`
context renders jOOQ Conditions with no connection at all. These three
specs extend that to the parts of the tier that are genuinely
connection-free.

- DashboardResourceSpec: getOrderFields is public and pure. Existing
  coverage (incidental, via WorkflowResourceSpec) only reached NameAsc/Desc,
  ExecutionTimeAsc/Desc and EditTime-via-default; this adds CreateTime both
  ways and the non-matching-orderBy fall-through. It also pins the
  asc/desc asymmetry -- Desc emits `desc nulls last` while Asc emits a bare
  `asc` -- which is what makes the behaviour symmetric, since Postgres
  defaults to NULLS LAST for ASC and NULLS FIRST for DESC. Plus the
  unknown-resourceType IllegalArgumentException, which is raised before any
  query is built and so needs no database.
- WorkflowSearchQueryBuilderSpec: toEntryImpl and mappedResourceSchema are
  callable because this object widens the trait's `protected` to public.
  Covers the projects-aggregate lookup (which rides on jOOQ structural
  Field equality), both branches of the comma-split, the NULL-privilege
  fallback to NONE, and the ownership flag both ways.
- UnifiedResourceSchemaSpec: the 24-slot projection and the keep-first
  de-duplication behind allFields, whose counts were measured rather than
  assumed (24 aliases, collapsing to 6 for the all-defaults schema and 17
  for the workflow schema).

Assertion strength was checked by mutation: reverting `nulls last`,
swapping an order field, inverting the isOwner comparison, changing the
privilege fallback, and disabling the de-dup guard each turn tests red.

No production file is touched.
@github-actions

Copy link
Copy Markdown
Contributor

Automated Reviewer Suggestions

Based on the git blame history of the changed files, we recommend the following reviewers:

  • No candidates found from git blame history.

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ Benchmark changes need a look

🟢 2 better · 🔴 5 worse · ⚪ 8 noise (<±5%) · 0 without baseline

Compared against main 301e3a8 benchmarked on this same runner, so the delta is largely free of cross-runner hardware noise. The "7d avg" column still reflects the gh-pages dashboard. Treat <±5% as noise unless repeated.

Dashboard · Run

config throughput MB/s latency max Δ latest / 7d
🔴 bs=10 sw=10 sl=64 429 0.262 22,629/31,749/31,749 us 🔴 +12.6% / 🔴 +101.3%
🟢 bs=100 sw=10 sl=64 940 0.574 108,416/117,542/117,542 us 🟢 -14.2% / 🔴 +9.5%
bs=1000 sw=10 sl=64 1,111 0.678 907,235/929,716/929,716 us ⚪ within ±5% / 🟢 -11.8%
Baseline details

Latest main 301e3a8 from same runner

config metric PR latest main 7d avg Δ latest Δ 7d
bs=10 sw=10 sl=64 throughput 429 tuples/sec 477 tuples/sec 786.12 tuples/sec -10.1% -45.4%
bs=10 sw=10 sl=64 MB/s 0.262 MB/s 0.291 MB/s 0.48 MB/s -10.0% -45.4%
bs=10 sw=10 sl=64 p50 22,629 us 20,100 us 12,305 us +12.6% +83.9%
bs=10 sw=10 sl=64 p95 31,749 us 30,120 us 15,774 us +5.4% +101.3%
bs=10 sw=10 sl=64 p99 31,749 us 30,120 us 18,978 us +5.4% +67.3%
bs=100 sw=10 sl=64 throughput 940 tuples/sec 955 tuples/sec 999.71 tuples/sec -1.6% -6.0%
bs=100 sw=10 sl=64 MB/s 0.574 MB/s 0.583 MB/s 0.61 MB/s -1.5% -5.9%
bs=100 sw=10 sl=64 p50 108,416 us 105,377 us 100,616 us +2.9% +7.8%
bs=100 sw=10 sl=64 p95 117,542 us 136,953 us 107,356 us -14.2% +9.5%
bs=100 sw=10 sl=64 p99 117,542 us 136,953 us 113,255 us -14.2% +3.8%
bs=1000 sw=10 sl=64 throughput 1,111 tuples/sec 1,128 tuples/sec 1,031 tuples/sec -1.5% +7.7%
bs=1000 sw=10 sl=64 MB/s 0.678 MB/s 0.688 MB/s 0.63 MB/s -1.5% +7.7%
bs=1000 sw=10 sl=64 p50 907,235 us 886,818 us 980,328 us +2.3% -7.5%
bs=1000 sw=10 sl=64 p95 929,716 us 925,214 us 1,027,528 us +0.5% -9.5%
bs=1000 sw=10 sl=64 p99 929,716 us 925,214 us 1,054,298 us +0.5% -11.8%
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,465.81,200,128000,429,0.262,22628.55,31749.12,31749.12
1,100,10,64,20,2127.50,2000,1280000,940,0.574,108415.59,117542.27,117542.27
2,1000,10,64,20,17999.89,20000,12800000,1111,0.678,907234.72,929715.67,929715.67

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.59%. Comparing base (fe9c490) to head (22d0b4f).
⚠️ Report is 5 commits behind head on main.
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #7116      +/-   ##
============================================
+ Coverage     79.40%   79.59%   +0.18%     
- Complexity     3803     3833      +30     
============================================
  Files          1159     1159              
  Lines         46142    46145       +3     
  Branches       5128     5127       -1     
============================================
+ Hits          36639    36728      +89     
+ Misses         7887     7786     -101     
- Partials       1616     1631      +15     
Flag Coverage Δ *Carryforward flag
access-control-service 70.00% <ø> (ø) Carriedforward from fe9c490
agent-service 77.42% <ø> (ø) Carriedforward from fe9c490
amber 73.13% <ø> (+0.51%) ⬆️
computing-unit-managing-service 20.49% <ø> (ø) Carriedforward from fe9c490
config-service 66.66% <ø> (ø) Carriedforward from fe9c490
file-service 67.21% <ø> (ø) Carriedforward from fe9c490
frontend 83.05% <ø> (ø) Carriedforward from fe9c490
notebook-migration-service 78.94% <ø> (ø) Carriedforward from fe9c490
pyamber 97.36% <ø> (ø) Carriedforward from fe9c490
workflow-compiling-service 26.31% <ø> (ø) Carriedforward from fe9c490

*This pull request uses carry forward flags. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aglinxinyuan
aglinxinyuan requested a review from mengw15 July 30, 2026 05:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add no-DB unit tests for the dashboard search query tier

2 participants