8000 feat(dashboard): decouple dataengine provider and parallelize multi-plot queries by AntonTyb · Pull Request #1407 · google/xmc · GitHub
[go: up one dir, main page]

Skip to content

feat(dashboard): decouple dataengine provider and parallelize multi-plot queries - #1407

Merged
AntonTyb merged 5 commits into
feat/metrics-ingester-bigquery-configfrom
feat/dataengine-query-backend-abstraction
Oct 27, 2026
Merged

AntonTyb merged 5 commits into
feat/metrics-ingester-bigquery-configfrom
feat/dataengine-query-backend-abstraction

Conversation

@AntonTyb
@AntonTyb AntonTyb commented Oct 25, 2026 •
Copy link
Copy Markdown
Collaborator

Stack (3/6): main ← #1405 ← #1406 ← #1407 (this PR) ← #1408 ← #1409 ← #1410 — review and merge bottom-up.

Summary

Introduces the package-internal queryBackend / rowScanner execution seam on DataEngine alongside exported EngineBuilder / EngineResolver constructors on Provider and DataEngine.Close() teardown, preparing internal/dashboard/dataengine for NewBigQuery in follow-up PR #1408 without exposing internal scanner interfaces. Also parallelizes multi-plot chart queries with a bounded errgroup while preserving deterministic output ordering.

Motivation & Context

DataEngine and Provider previously coupled connection dialing, dynamic configuration reload, and query execution directly to ClickHouseConn. Decoupling query execution behind an internal backend contract, generalizing Provider onto EngineBuilder / EngineResolver, and parallelizing multi-plot FetchChartData calls prepares dashboard_service for higher-latency cloud analytics backends such as BigQuery (which incurs ~200–800ms per query) without duplicating singleflight caching, readiness probes, or graceful connection teardown.

Key Changes

  • Introduce internal rowScanner and queryBackend interfaces with clickHouseBackend and DataEngine.Close() in internal/dashboard/dataengine/querier.go and internal/dashboard/dataengine/engine.go, plus maxChartWidthPixels request clamping.
  • Execute multi-plot FetchChartData queries concurrently via a bounded errgroup (maxConcurrentPlots = 8) while executing single-plot charts inline and preserving chart.GetPlots() output slice order.
  • Add EngineBuilder, EngineResolver, NewEngineProvider, NewDynamicEngineProvider, and Provider.Close() in internal/dashboard/dataengine/provider.go, deduplicating dynamic rebuilds via singleflight with ctx.Done() caller abort and retryInterval rate-limiting while delegating NewProvider and NewDynamicProvider for full backward compatibility.
  • Register defer de.Close() during cmd/dashboard_service shutdown and add unit tests in querier_test.go, engine_test.go, and provider_test.go.

Assumptions

  • Bounding concurrent per-chart plot queries at maxConcurrentPlots = 8 balances multi-plot dashboard latency against backend connection/slot concurrency limits — chosen because BigQuery interactive queries share a per-project concurrent query quota and ClickHouse connection pools are finite — if charts routinely contain dozens of plots under low concurrency, increasing or parameterizing this cap may improve tail latency without breaking API contracts.

Verification & Testing

  • Commands Executed: bazel test --runs_per_test=10 --@io_bazel_rules_go//go/config:race //internal/dashboard/dataengine/... //cmd/dashboard_service/..., bazel coverage --combined_report=lcov //internal/dashboard/dataengine/..., ./.githooks/pre-commit
  • Coverage & Test Status: All unit tests pass across 10 race-enabled runs; pre-commit hooks and affected test suite pass.

Related Issues / Bugs

N/A

TAG=agy
CONV=0fafd02b-f3b1-4563-a73d-49ec0845afbd

…lot queries

Generalize `internal/dashboard/dataengine` engine construction, lifecycle
management, and multi-plot execution so analytics backends beyond ClickHouse
can plug into `DataEngine` and `Provider` without duplicating readiness,
singleflight caching, or graceful teardown logic.

- Introduce internal `rowScanner` and `queryBackend` interfaces in
  `internal/dashboard/dataengine` with `clickHouseBackend` and `DataEngine.Close()`.
- Execute multi-plot `FetchChartData` queries concurrently via a bounded
  `errgroup` (`maxConcurrentPlots = 8`) while running single-plot charts inline
  and preserving deterministic `chart.GetPlots()` output slice order.
- Add backend-agnostic `EngineBuilder`, `EngineResolver`, `NewEngineProvider`,
  `NewDynamicEngineProvider`, and `Provider.Close()`, delegating `NewProvider`
  and `NewDynamicProvider` through them and wiring `defer de.Close()` in
  `cmd/dashboard_service`.

TAG=agy
CONV=0fafd02b-f3b1-4563-a73d-49ec0845afbd

Change-Id: I22e0e82bdeef95d5dcdef8a3b06dd88e2ec4f43b
@gemini-code-assist gemini-code-assist Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the dashboard data engine to abstract the database backend using a new queryBackend interface and generalizes the provider to support backend-agnostic engine building. It also introduces concurrent plot data fetching using errgroup, adds resource cleanup with a Close method, and expands test coverage. The review feedback correctly identifies a potential nil pointer dereference in fetchPlotData when a chart contains a nil plot element, recommending a defensive nil check to prevent runtime panics.

Comment thread internal/dashboard/dataengine/engine.go Resolved
@AntonTyb
AntonTyb marked this pull request as ready for review October 26, 2026 06:55
@github-actions
github-actions Bot requested a review from janzak-dev October 26, 2026 06:55
@VLukiantsev
VLukiantsev added this pull request to stack #1412 October 26, 2026 09:37
Comment thread internal/dashboard/dataengine/engine.go Resolved
Comment thread internal/dashboard/dataengine/engine.go Resolved
Comment thread internal/dashboard/dataengine/engine.go Resolved
…at/dataengine-query-backend-abstraction

Sync downstream stack branch with PR #1405/#1406 ancestry.

TAG=agy
CONV=0fafd02b-f3b1-4563-a73d-49ec0845afbd

Change-Id: If1841fa3894b857f6480650ecad7292bc3eea1f1
…at/dataengine-query-backend-abstraction

Change-Id: I2d024f1bba0599cb3f6122d869b46b09e94d9fbf
…ovider

- Clamp `req.GetChartWidthPixels()` to `maxChartWidthPixels` (`4000`) in
  `FetchChartData`.
- Remove duplicate `conn ClickHouseConn` field from `DataEngine` and unused
  `QueryRow` from `ClickHouseConn` / `mockClickHouseConn`.
- Deduplicate dynamic engine rebuilds via `singleflight` (`DoChan`) with
  `ctx.Done()` caller cancellation abort and per-fingerprint `retryInterval`
  rate-limiting so `/readyz` probes never pile up behind slow dials.
- Assert `logging.Warn` output during dynamic resolution and rebuild failures
  in `provider_test.go`.

TAG=agy
CONV=0fafd02b-f3b1-4563-a73d-49ec0845afbd

Change-Id: I1a243b1b0446ff373cabe24b0453bc29e1780645
@AntonTyb
AntonTyb requested a review from janzak-dev October 27, 2026 12:46
janzak-dev
janzak-dev previously approved these changes Oct 27, 2026
Delegate `Provider.Ping` and `Provider.pingDynamic` tail checks to
`pingActive(ctx, errProviderClosed)` so a concurrent `Provider.Close()`
(`p.engine.Swap(nil)`) returns `errProviderClosed` cleanly instead of
relying on concrete nil-receiver dispatch. Also short-circuit
`beginAttempt` and `beginRebuildAttempt` when `p.closed` is true so
post-`Close` calls within `retryInterval` never return `(nil, nil)` or
redial a closed provider.

Comment link: #1407 (comment)

Change-Id: I177b1b7ab286554f619ed3c2b5d816db4ff7e522
@github-actions github-actions Bot left a comment
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Incremental PR Approval

PR author is a code owner and changes since last approval (17 lines, excluding 95 test file lines) are within the 50-line grace delta.

Preserving prior approval by @janzak-dev on commit 0d4029c.

@AntonTyb
AntonTyb added this pull request to the merge queue Oct 27, 2026
Merged via the queue into main with commit 5738dfc Oct 27, 2026
14 checks passed
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.

2 participants

0