fix(api-gateway): poll a pre-agg job on the data source that built it - #11666
Conversation
`POST /v1/pre-aggregations/jobs { action: 'get' }` threw
`TypeError: Cannot read properties of undefined (reading 'getQueueDriver')`
once a job had left the queue. #11617 stopped the crash by creating the queue client
lazily in `isPartitionExist`; this fixes why the data source was wrong in the first
place, which otherwise makes the poll read a foreign queue — build failures never
surface as `failure: …` and the job cache stops being updated.
`getPreAggJobResultStatus` read the data source from `metaConfigExtended()`'s
`cubeDefinitions`, which is the raw definition map: `extends` inheritance only exists on
the built cube (`createCube` sets the prototype on a copy), so an inherited `data_source`
is invisible there.
| model | `cubeDefinitions.orders.dataSource` | `evaluatedCubes.orders.dataSource` |
| --- | --- | --- |
| YAML, `data_source` on the cube | `named_data_source` | `named_data_source` |
| YAML, `data_source` via `extends` | undefined | `named_data_source` |
| JS, `dataSource` on the cube | `named_data_source` | `named_data_source` |
So the build queued on `named_data_source` while the poll asked for `default`. A single
replica is enough to hit this; the shared Cube Store queue in the report is not required.
A posted job also returns one entry per built pre-aggregation — the partition plus every
dependency — and each entry becomes its own polling token. Two of them were mislabelled:
- `RefreshScheduler` set `dataSource` / `timezone` on `job[0]` only, so entries 1..n were
cached with `undefined` and polled on the `default` queue
- `QueryOrchestrator` stamped every entry with `preAggregations[0].preAggregationId`, so
`job.preagg` named the first dependency for all of them and the gateway resolved the
wrong pre-aggregation — and with it the wrong `external` flag
Both only bite when a build has dependencies (lambda rollups, or a rollup on top of an
`originalSql` pre-aggregation).
- query-orchestrator: each result entry carries the `preAggregationId`, `dataSource` and
`timezone` of the descriptor it was built from, so a jobed build self-describes
- server-core: label every entry of a posted job, falling back to the partition
- schema-compiler: `PreAggregationInfo` exposes the resolved `dataSource`
- gateway: poll on `job.dataSource`, falling back to the model for jobs cached before this
landed; `metaConfigExtended` is no longer needed on this endpoint
Fixes #11615
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @ovr's task in 3m 20s —— View job Review complete — approach is sound; 1 medium, 3 low. 2 inline comments posted.Full review
SummaryThe diagnosis holds up. Two things I liked: dropping Findings
3 — type honesty. 4 — dead branch. TestingCoverage is well-targeted at the three seams that broke — per-entry labelling in
Security / performanceNothing of concern. No new input reaches a driver unsanitized — Not verifiedI could not run the test suites — the checkout has no installed dependencies ( |
The fallback to the pre-aggregation's data source lived inside getPreAggJobResultStatus, so the two other consumers of the data source in the same handler did not see it: the queue probe passed the raw job.dataSource into getPreAggregationQueueStates, which defaults to 'default', and the response selector reported dataSources: [undefined]. For a job posted before the data source was recorded — one still within its day-long cache TTL, or one written by another instance mid-deploy — the queue was then read on 'default', nothing matched, and a build still sitting in a non-default queue as scheduled/processing was reported as missing_partition. Resolve the data source once, before the status branch, and pass it to the selector, the queue lookup and the partition check so all three agree. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @ovr's task in 1m 34s —— View job Re-review of
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #11666 +/- ##
==========================================
+ Coverage 58.20% 58.38% +0.18%
==========================================
Files 237 237
Lines 18852 18853 +1
Branches 3825 3830 +5
==========================================
+ Hits 10973 11008 +35
+ Misses 7323 7283 -40
- Partials 556 562 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Check List
Issue Reference this PR resolves
Fixes #11615
Description of Changes Made (if issue reference is not provided)
#11617 stopped the
Cannot read properties of undefined (reading 'getQueueDriver')crash by creating the queue client lazily, but the data source handed toisPartitionExistwas still wrong, so the poll read a foreign queue and build failures never surfaced asfailure: …. The gateway took it frommetaConfigExtended().cubeDefinitions, which is the raw definition map —extendsinheritance only exists on the built cube, so an inheriteddata_sourcereads asundefinedand falls back todefaultwhile the build queued on the named one; it now usesjob.dataSource, falling back to a resolveddataSourcenewly exposed onPreAggregationInfo, which also lets the expensivemetaConfigExtendedcall drop off this polling endpoint. A posted job additionally returns one entry per built pre-aggregation (the partition plus every dependency) and each becomes its own token, butRefreshSchedulerlabelled onlyjob[0]andQueryOrchestratorstamped every entry withpreAggregations[0].preAggregationId— so entries1..nwere cached withdataSource: undefinedand the gateway resolved the wrong pre-aggregation andexternalflag. Each result entry now carries thepreAggregationId,dataSourceandtimezoneof the descriptor it was built from, so a jobed build self-describes; this only bites builds with dependencies (lambda rollups, or a rollup on top of anoriginalSqlpre-aggregation). Covered by new unit tests incubejs-query-orchestrator(QueryOrchestrator.jobs.test.ts,PreAggregations.test.ts) andcubejs-api-gateway.🤖 Generated with Claude Code