Repository navigation
feat: Add chart-owned runtime data limits and issue reporting - #656
Conversation
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughAdds chart-runtime types/utilities, per-panel runtime issue state and APIs, chart-type data-policy hooks, renderer/client enforcement/reporting of policies and issues, and AI/tooling exposure of panel issues used by repair workflows. ChangesChart Runtime Issue Tracking
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/mosaic/src/VgPlotChart.tsx (1)
194-221:⚠️ Potential issue | 🟠 Major | ⚡ Quick winFix cached-chart lifecycle so
dataPolicy/ runtime issue props can’t go stale.
MosaicDashboardChartContentalready memoizesdataPolicy,runtimeIssueContext, andruntimeIssueReporterwithuseMemo, so inline-object remount concerns at those call sites are already handled.- Still,
useVgPlotChartRenderreturns early whencachedChartis present and never re-wrapsplot.marks[*].queryResult/queryError; sinceuseVgPlotChartRetentionkeys only byspecKey+ params, changingdataPolicy/runtimeIssue* can leave the cached chart using stale closure values (wrong policy assertion / wrong runtime issue reporting).🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mosaic/src/VgPlotChart.tsx` around lines 194 - 221, The cached chart can hold stale closures for dataPolicy/runtimeIssue reporting because useVgPlotChartRender returns early when cachedChart exists; update the hook so when a cachedChart is found it either (A) invalidates the cache based on dataPolicy/runtimeIssueContext/runtimeIssueReporter changes (add those to the cache key used by useVgPlotChartRetention along with specKey+params) or (B) after retrieving cachedChart, re-wrap each mark’s runtime handlers (iterate cachedChart.plot.marks and replace mark.queryResult and mark.queryError with wrappers that call the current dataPolicy/runtimeIssueContext/runtimeIssueReporter) so the cached chart uses fresh closures; reference useVgPlotChartRender, useVgPlotChartRetention, cachedChart, plot.marks[*].queryResult/queryError, specKey, params, dataPolicy, runtimeIssueContext, runtimeIssueReporter when making the change.
🧹 Nitpick comments (3)
packages/mosaic/__tests__/chart-runtime.test.ts (1)
21-35: ⚡ Quick winAdd a regression test for
maxRows: 0.Given policy semantics, zero should be a valid hard limit. Adding this test will lock in boundary behavior.
Suggested test case
it('skips disabled policies and supports custom size estimators', () => { @@ }); + + it('enforces zero-row limits when maxRows is 0', () => { + expect(() => assertChartDataPolicy({maxRows: 0}, [{x: 1}])).toThrow( + DataPointLimitError, + ); + expect(() => assertChartDataPolicy({maxRows: 0}, [])).not.toThrow(); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mosaic/__tests__/chart-runtime.test.ts` around lines 21 - 35, Add a regression test that verifies maxRows: 0 is treated as a valid hard limit: using assertChartDataPolicy with {maxRows: 0} and an empty data array should not throw, while using {maxRows: 0} with any non-empty array (e.g., [{x:1}]) should throw DataPointLimitError; place this assertion alongside the existing tests that call assertChartDataPolicy and reference the same DataPointLimitError to lock in the boundary behavior.packages/mosaic/src/useVgPlotChartRender.ts (1)
154-173: ⚡ Quick winSubtle: catch-path delegates to
mark.queryError, which by then is the wrapped version.In the
queryResultcatch branch you callmark.queryError(normalizedError)(line 160). Because the sameforEachiteration installs thequeryErrorwrapper a few lines later (175–197), the runtime call dispatches to the wrapper — so the issue is still reported via that path. This is correct but fragile: if the twoifblocks are ever reordered or the wrapping is split, theruntimeIssueContextbranch at lines 162–170 will be silently skipped whenevermark.queryErrorexists. A short comment explaining the dependency, or moving the explicitreportIssuecall out of theelseso it always fires on failure, would harden this.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mosaic/src/useVgPlotChartRender.ts` around lines 154 - 173, In the queryResult catch branch, ensure the runtime issue is always reported regardless of whether mark.queryError is present: move or duplicate the runtimeIssueReporter?.reportIssue(createChartRuntimeIssueFromError(normalizedError, runtimeIssueContext, dataPolicy)) call so it executes before delegating to mark.queryError(normalizedError) (or call it unconditionally then call mark.queryError if present), and/or add a short comment clarifying the ordering dependency; update the catch block around mark.queryError, runtimeIssueContext, runtimeIssueReporter, and createChartRuntimeIssueFromError to guarantee reporting always happens prior to or independent of the wrapped mark.queryError invocation.packages/mosaic/src/useMosaicClient.ts (1)
110-121: ⚡ Quick win
onQueryErrorforwards rawunknown; consider normalizing for consistency.
useVgPlotChartRendernormalizes thrown values toErrorbefore reporting/forwarding, but here the rawerror: unknownis passed both tocreateChartRuntimeIssueFromErrorand toqueryErrorRef.current. If a non-Error value (string, DOMException, etc.) bubbles up from Mosaic, downstream consumers expectingError(e.g..message) may break. Normalize once and reuse:♻️ Suggested change
onQueryError: (error) => { + const normalizedError = + error instanceof Error ? error : new Error(String(error)); if (runtimeIssueContextRef.current) { runtimeIssueReporterRef.current?.reportIssue( createChartRuntimeIssueFromError( - error, + normalizedError, runtimeIssueContextRef.current, dataPolicyRef.current, ), ); } - queryErrorRef.current?.(error); + queryErrorRef.current?.(normalizedError); },🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/mosaic/src/useMosaicClient.ts` around lines 110 - 121, Normalize the incoming unknown `error` in `onQueryError` to an actual `Error` instance before using it: create a normalized Error (e.g., via a small helper or `error instanceof Error ? error : new Error(String(error))`) and pass that same normalized Error into `createChartRuntimeIssueFromError(...)` and to `queryErrorRef.current(...)` so downstream consumers always receive an Error object; update the `onQueryError` handler in `useMosaicClient` to perform this single normalization and reuse the normalized value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/mosaic/src/chart-runtime.ts`:
- Around line 69-72: The warning in getQueryResultRowCount currently prints the
full result payload (result) which can leak sensitive data; change the
console.warn in that function to avoid including result directly—either remove
the result argument entirely or replace it with a safe summary (e.g., typeof
result, Array.isArray(result), a boolean for presence of toArray, or a bounded
length/row count) so logs show only non-sensitive shape/metadata and not the raw
data.
- Around line 80-82: The early-return treats policy.maxRows falsy (so 0) as "no
limit"; change the check in the validation guard so that it only returns when
policy is missing or disabled or when maxRows is null/undefined (not when it
equals 0). Locate the guard that reads "if (!policy || policy.disabled ||
!policy.maxRows) return;" and replace the maxRows falsy check with an explicit
undefined/null check (e.g., policy.maxRows == null) so policies with maxRows: 0
are validated.
---
Outside diff comments:
In `@packages/mosaic/src/VgPlotChart.tsx`:
- Around line 194-221: The cached chart can hold stale closures for
dataPolicy/runtimeIssue reporting because useVgPlotChartRender returns early
when cachedChart exists; update the hook so when a cachedChart is found it
either (A) invalidates the cache based on
dataPolicy/runtimeIssueContext/runtimeIssueReporter changes (add those to the
cache key used by useVgPlotChartRetention along with specKey+params) or (B)
after retrieving cachedChart, re-wrap each mark’s runtime handlers (iterate
cachedChart.plot.marks and replace mark.queryResult and mark.queryError with
wrappers that call the current
dataPolicy/runtimeIssueContext/runtimeIssueReporter) so the cached chart uses
fresh closures; reference useVgPlotChartRender, useVgPlotChartRetention,
cachedChart, plot.marks[*].queryResult/queryError, specKey, params, dataPolicy,
runtimeIssueContext, runtimeIssueReporter when making the change.
---
Nitpick comments:
In `@packages/mosaic/__tests__/chart-runtime.test.ts`:
- Around line 21-35: Add a regression test that verifies maxRows: 0 is treated
as a valid hard limit: using assertChartDataPolicy with {maxRows: 0} and an
empty data array should not throw, while using {maxRows: 0} with any non-empty
array (e.g., [{x:1}]) should throw DataPointLimitError; place this assertion
alongside the existing tests that call assertChartDataPolicy and reference the
same DataPointLimitError to lock in the boundary behavior.
In `@packages/mosaic/src/useMosaicClient.ts`:
- Around line 110-121: Normalize the incoming unknown `error` in `onQueryError`
to an actual `Error` instance before using it: create a normalized Error (e.g.,
via a small helper or `error instanceof Error ? error : new
Error(String(error))`) and pass that same normalized Error into
`createChartRuntimeIssueFromError(...)` and to `queryErrorRef.current(...)` so
downstream consumers always receive an Error object; update the `onQueryError`
handler in `useMosaicClient` to perform this single normalization and reuse the
normalized value.
In `@packages/mosaic/src/useVgPlotChartRender.ts`:
- Around line 154-173: In the queryResult catch branch, ensure the runtime issue
is always reported regardless of whether mark.queryError is present: move or
duplicate the
runtimeIssueReporter?.reportIssue(createChartRuntimeIssueFromError(normalizedError,
runtimeIssueContext, dataPolicy)) call so it executes before delegating to
mark.queryError(normalizedError) (or call it unconditionally then call
mark.queryError if present), and/or add a short comment clarifying the ordering
dependency; update the catch block around mark.queryError, runtimeIssueContext,
runtimeIssueReporter, and createChartRuntimeIssueFromError to guarantee
reporting always happens prior to or independent of the wrapped mark.queryError
invocation.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 90bb4f67-d625-4c86-8293-8d6e97b49162
📒 Files selected for processing (26)
packages/mosaic/__tests__/MosaicDashboardRuntimeIssue.test.tspackages/mosaic/__tests__/chart-runtime.test.tspackages/mosaic/__tests__/dashboard-ai.test.tspackages/mosaic/src/MosaicSlice.tspackages/mosaic/src/VgPlotChart.tsxpackages/mosaic/src/VgPlotChartError.tsxpackages/mosaic/src/ai.tspackages/mosaic/src/boxplot/BoxPlotClient.tspackages/mosaic/src/chart-runtime.tspackages/mosaic/src/chart-types/base-types.tspackages/mosaic/src/chart-types/box-plot/definition.tspackages/mosaic/src/chart-types/box-plot/renderer/BoxPlotPanelRenderer.tsxpackages/mosaic/src/chart-types/box-plot/renderer/useBoxPlotClient.tspackages/mosaic/src/chart-types/bubble-chart/definition.tspackages/mosaic/src/chart-types/custom-spec/definition.tspackages/mosaic/src/chart-types/line-chart/definition.tspackages/mosaic/src/chart-types/list-panels-tool.tspackages/mosaic/src/chart/ChartRuntimeIssuePanel.tsxpackages/mosaic/src/chart/MosaicDashboardChartContent.tsxpackages/mosaic/src/chart/MosaicDashboardComponentChart.tsxpackages/mosaic/src/chart/MosaicDashboardVgPlotChart.tsxpackages/mosaic/src/dashboard/MosaicDashboardSlice.tspackages/mosaic/src/index.tspackages/mosaic/src/useMosaicClient.tspackages/mosaic/src/useVgPlotChartRender.tspackages/mosaic/src/wrapCoordinatorWithValidation.ts
💤 Files with no reviewable changes (1)
- packages/mosaic/src/MosaicSlice.ts
Summary by CodeRabbit
New Features
Improvements
Tests