feat(tesseract): native Rust time-series generation#10980
Conversation
Add QueryTimeSeries to planner/time_dimension with two entry points:
* generate_predefined(granularity, range, precision) — snaps the
start to the bucket boundary (day / week ISO-Mon / month / quarter
/ year / hour / minute / second) and emits buckets until past the
end. Sub-second part padded with '0' / '9' to the requested precision.
* generate_custom(interval, range, origin, precision) — aligns to
origin, walks by parsed SqlInterval (calendar-aware for month /
quarter / year via chrono::Months, fixed Duration for sub-day),
end = next - 1 second. Iteration capped at 50k buckets.
physical_plan::TimeSeries and MockBaseTools now route through the Rust
impl for drivers without generated-series support; the bridge
generate_time_series / generate_custom_time_series calls disappear from
the planner path. The mock-only helper test_fixtures/cube_bridge/
time_series.rs is deleted — the new module covers it with 15 inline
tests for predefined / custom shapes.
A custom granularity with a week-only interval (e.g. "2 weeks") and no explicit origin/offset fell back to the default origin (start of the current year) without snapping to the start of the week. That produced bucket boundaries offset from the expected Monday-aligned grid. Snap the default origin to the ISO Monday when the interval is week-only, applied in both the default and offset branches of Granularity. Adds SqlInterval::is_week_only and QueryDateTime::start_of_iso_week, covered by deterministic unit tests in granularity.rs.
Enable the previously-ignored half_year / bi_weekly / to_date rolling window tests now that the Rust time-series path generates the buckets. Pin an explicit origin on the bi_weekly fixture granularity so its bucket alignment no longer depends on the current year, keeping the snapshot stable. Commit the reviewed insta baselines (verified against the seed data).
The planner now generates time series via QueryTimeSeries, so the BaseTools bridge no longer calls generate_time_series / generate_custom_time_series. Remove them from the native_bridge trait and the mock. The JavaScript implementations stay in place for the legacy planner.
- Drop the now-removed generate_time_series / generate_custom_time_series from the cubejs-backend-native bridge test exports (StubBaseTools impl and invoke_base_tools) and the matching JS bridge fixtures / coverage list, so the native crate compiles after the BaseTools trait change. - Cap generate_predefined at the shared MAX_BUCKETS (hoisted to module level) so a wide range at second/minute granularity errors instead of looping unbounded. - add_interval_to_dt: return the combined datetime directly and note the fixed unit-application order.
Add unit tests for previously-uncovered QueryTimeSeries paths: - custom MAX_BUCKETS cap - months+days and sub-day intervals in add_interval_to_dt - the non-advancing (net-negative) interval guard - precision-6 padding on the custom path - quarter and year custom intervals
|
Claude finished @waralexrom's task in 1m 46s —— View job Claude PR ReviewVerdict: Approve with nits — 1 medium (latent infinite-loop in DetailsTodos
SummaryThis is a clean, well-scoped move: the JS bridge methods Test coverage is good: predefined paths cover every granularity unit + precision-6 padding + the cap; custom paths cover origin-before-start, origin-after-start (back-walk), calendar months, mixed month+day, sub-day, quarter, year, zero/garbage intervals, the bucket cap, and the non-advancing-interval guard. The new Inline findings
Praise
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #10980 +/- ##
=======================================
Coverage 78.84% 78.84%
=======================================
Files 470 470
Lines 93390 93390
Branches 3466 3466
=======================================
Hits 73637 73637
Misses 19250 19250
Partials 503 503
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
- Guard both align_to_origin loops with a MAX_BUCKETS cap so a net-negative or net-zero interval errors instead of spinning the planner thread; add a regression test for start < origin. - Document the intentional inclusive (predefined) vs exclusive (custom) range-end handling. - Tighten the add_interval_to_dt comment: SqlInterval is field-based, so month-end clamping happens before days are added.
|
Claude finished @waralexrom's task in 39s —— View job Claude PR Review (re-review)Verdict: Approve — all 3 prior findings addressed in d169333. No new issues. DetailsTodos
Resolution of prior review
All three corresponding inline threads resolved. Re-review passWalked the rest of the diff for anything the prior pass might have missed. Nothing new surfaced:
|
Summary
Move time-series bucket generation for the Tesseract (Rust) planner from the JS bridge into native Rust. The planner no longer calls back into JavaScript to build time series, and the dead bridge methods are removed.
Changes
QueryTimeSeries(planner/time_dimension/time_series.rs) withgenerate_predefinedandgenerate_custom, mirroring the established bucket/alignment/padding semantics; both paths are capped at a shared module-levelMAX_BUCKETS.physical_plan::TimeSeriesand the mock through the Rust impl for drivers without generated-series support; delete the old mock-only helper.fixOriginForWeeksIfNeeded), viaSqlInterval::is_week_only+QueryDateTime::start_of_iso_week.generate_time_series/generate_custom_time_seriesfrom theBaseToolsbridge trait and its consumers incubejs-backend-native(StubBaseTools, invoke_base_tools, JS bridge fixtures). The JS implementations stay for the legacy planner.Testing
cargo test -p cubesqlplanner— time_series unit tests (predefined/custom shapes, bucket cap, calendar intervals, precision, alignment) and rolling_window integration tests (snapshots verified against seed data) pass.cargo buildofcubejs-backend-nativecompiles after the bridge change.cargo fmt --checkclean.