Skip to content

feat: add live views support - #605

Open
emrberk wants to merge 13 commits into
mainfrom
feat/live-views
Open

feat: add live views support#605
emrberk wants to merge 13 commits into
mainfrom
feat/live-views

Conversation

@emrberk

@emrberk emrberk commented Aug 31, 2026

Copy link
Copy Markdown
Member

Adds live views to the Web Console as a first-class schema object.

Live views

  • The schema tree gains a Live views folder with its own icon, search, tooltips and context menu.
  • The details drawer supports live views: status, base table, DDL and columns, plus a monitoring tab with freshness (unflushed transactions, time since last flush, writer stall) and in-memory tier (rows, footprint, dropped rows) metrics.
  • Invalid, state-unreadable and version-unsupported live views raise a critical banner with recovery guidance, both in the tree and in the drawer.
  • A suspended live view can be resumed from the tree; the console issues ALTER LIVE VIEW '<name>' RESUME WAL.
  • The AI assistant and MCP tools can list, explain and inspect live views alongside tables, views and materialized views.

Health rules for live views

Live view specific:

Code Severity Reason
R5 Critical view_status is invalid. Shows invalidation_reason.
R6 Critical view_status is version_unsupported. Server build cannot read the on-disk format.
R7 Critical view_status is state_unreadable. State files corrupt or missing.
Y7 Warning writer_stall_micros above 5 s on the current poll. Readers pin both memory slots.

Shared WAL rules that also apply to a live view:

Code Severity Reason
R1 Critical WAL suspended.
R3 Critical Memory pressure level 2, backoff.
Y1 Warning Transaction lag rising above 0.5 txn/s over 30 s. Debounced 5 s.
Y2 Warning Pending rows rising above 0.5 rows/s over 30 s. Debounced 5 s.
Y3 Warning Transaction size p90 under 100 rows.
Y4 Warning Write amplification p50 at or above 3x.
Y5 Warning Memory pressure level 1, reduced parallelism.

If live_views() fails, overall status becomes Unknown and all live view fields show Unavailable.

Other user-visible changes

  • Catalog counters keep full 64-bit precision. LONG columns from tables(), materialized_views() and live_views() are read as bigint, so large row counts and transaction numbers are no longer rounded in the drawer or in AI prompts.
  • Storage policy is read from the storage_policies catalog instead of being parsed out of DDL text, so the Details tab reflects policy changes live, including a disabled policy.
  • The drawer reports unreachable metadata explicitly. Each metadata source shows an "Unavailable" state and retries on its own, keeping the last good values rather than blanking the panel.
  • The write amplification warning now fires at 3.0x, up from 2.0x, to cut noise on tables where O3 merges are expected.
  • The schema filter no longer crashes when the query contains a regular-expression character such as ( or [.
  • Invalid view messages no longer print null when the server reports no invalidation reason.

@emrberk

emrberk commented Sep 2, 2026

Copy link
Copy Markdown
Member Author

PR #605 Review

Review level: 3
Reviewed HEAD: 5bcc895d66e7dbbe42b3c0a7a29b77181e8186c5

Issues

Issue ID Issue name Category Severity Location Net impact Evidence Description Steps to reproduce Suggested fix
#1 Stale live-view health Query execution & data integrity Moderate in-diff — src/scenes/Schema/index.tsx:208 Live-view operators: stale health persists after each failed refresh. Targeted Cypress scratch test: passed at 5bcc895d; base N/A—new live-view tree surface. A successful tables() refresh marks the schema ready, but a failed live_views() request is silently ignored. The previous metadata remains attached to the row and is displayed without any stale or unavailable indication. A later successful refresh recovers it, but until then the schema tree presents last-known health as current. 1. Load a live view with an invalid status.
2. Make the next tables() request succeed.
3. Return a query error from live_views().
4. Refresh the schema and observe that the old invalid warning remains.
Represent live-view metadata with loading/ready/error state. Clear or stale-mark the retained value when the refresh fails and render an unavailable indicator.
#2 Quoted symbol details fail Query execution & data integrity Moderate out-of-diff — src/utils/questdb/client.ts:501; catalog-derived identifier escaping contract Quoted-alias users: symbol metadata silently disappears on expansion. Targeted Cypress scratch test: passed at 5bcc895d; exact malformed SQL failed against QuestDB while the escaped form succeeded. Base N/A—new live-view consumer. QuestDB permits a live-view output alias such as "sym'quote". Expanding that SYMBOL column reaches showSymbolColumnDetails, which emits WHERE column = 'sym'quote'. QuestDB rejects the malformed query, and the UI replaces the loading children with an empty list without displaying an error. 1. Create a live view projecting a SYMBOL as "sym'quote".
2. Expand Live views, the view, and Columns.
3. Expand sym'quote.
4. Observe no symbol capacity/cache/index details and the malformed /exec query.
Apply escapeSqlLiteral to the table and column literals in showSymbolColumnDetails; add a query-construction regression test for the quoted alias.
#3 Duplicate AI explanation requests Async, timers & cancellation Moderate in-diff — src/hooks/useAIQuickActions.ts:90 Live-view AI users: two provider calls per rapid double-click. Targeted Cypress falsifier: 1 passing at 5bcc895d, observing two DDL requests and exactly two OpenAI POSTs. Base N/A—new live-view AI path. Both clicks pass the render-captured AI-status guard and wait for separate DDL requests. The busy status is set only later inside executeAIFlow, so both continuations start provider requests. This can charge the user twice and produce a nondeterministic retained conversation turn. 1. Open a live view's Details tab with AI configured.
2. Delay SHOW CREATE LIVE VIEW responses.
3. Double-click Explain with AI.
4. Observe two DDL requests followed by two provider POSTs.
Claim an in-flight operation synchronously before fetching DDL, preferably with a ref keyed by table/kind, and clear it in finally.
#4 Keyboard-inaccessible metric help Accessibility & UX Moderate in-diff — src/scenes/Schema/TableDetailsDrawer/MonitoringTab.tsx:453 Keyboard-only users: four live-view explanations are unreachable. N/A—static proof at 5bcc895d: Radix Trigger asChild wraps an SVG with no tabIndex, role, or focusable parent. The help text for Unflushed Transactions, Since Last Flush, Rows in Memory, and Dropped Below Start From is available only through tooltips triggered by bare SVG icons. Keyboard focus skips those icons, so the explanatory text cannot be opened or announced. 1. Open a live view's Monitoring tab.
2. Navigate through the drawer using Tab.
3. Observe that none of the metric information icons receives focus.
4. The fourth icon appears when dropped-row counters are positive or diagnostics are unavailable.
Wrap each icon in a native button type="button" with an aria-label, using the button as Radix's asChild trigger.

Summary

  • Verdict: approve with comments
  • Correctness gate: passed (yarn test:unit, yarn typecheck, yarn build)
  • Test gate: passed; 0 admitted coverage gaps.
  • Severity: 4 Moderate
  • Location split: 3 in-diff, 1 out-of-diff.
  • Quality checks passed: typecheck, build, lint, and 2,064 unit tests.
  • Browser checks passed: the existing table-details suite passed 58/58; focused review artifacts passed 2/2 and 1/1.
  • PR title follows Conventional Commits and its description is user-impact oriented.

@emrberk
emrberk marked this pull request as ready for review September 8, 2026 13:07
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown

Web Console deploy preview

Preview Commit Logs
https://pr-605--web-console.netlify.app 8ae73a2 build log

@puzpuzpuz

Copy link
Copy Markdown
Contributor

Approve with comments on PR #605, reviewed at 61c05fa.

ID Issue Category Severity Location Net impact Evidence Description Reproduce Suggested fix
#1 Metric help lacks focusability Accessibility & UX Moderate in-diff — MonitoringTab.tsx:694 Keyboard users lack an explicit focus target for metric help. Static source at 61c05fa “Unflushed Transactions” uses a bare SVG as the tooltip trigger, without a native button or tabIndex. Radix requires a focusable trigger. Open live-view Monitoring; inspect the help trigger’s markup. Wrap the icon in a labeled button type="button".

Typecheck, build, lint, and 2,102 unit tests passed. Browser tests weren’t run in this level-2 review.

Correctness and test gates passed; zero admitted coverage gaps. Findings: 1 Moderate, 0 Critical, 0 Minor; 1 in-diff, 0 out-of-diff. Catalog, AI/MCP, and sidebar callers remain compatible with the changed contracts. No production files changed.

@puzpuzpuz
puzpuzpuz self-requested a review September 9, 2026 16:12
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