Skip to content

Feat/studio intelligent UI - #185

Merged
dwickyfp merged 9 commits into
mainfrom
feat/studio-intelligent-ui
Oct 14, 2026
Merged

dwickyfp merged 9 commits into
mainfrom
feat/studio-intelligent-ui

Conversation

@dwickyfp

Copy link
Copy Markdown
Owner

No description provided.

dwickyfp and others added 9 commits October 6, 2026 21:07
… off the event loop

One backend process served the application API, SQL and ML execution, and
the MySQL proxy on a single event loop, so a heavy statement or a BI client
slowed the whole application.

NOVA_PROCESS_ROLE (all, web, query) now decides which startup duties a
process runs. `all` is unchanged. A split deployment runs one web process
(schema bootstrap and singleton loops), any number of query processes for
/api/v1/query and /api/v1/ml, and `python -m app.proxy` for MySQL, behind
a path-routing gateway. docker-compose.split.yml and `./dev.sh --split`
run that topology; the default stack is untouched.

Inside a process, statements of 8 KB or more are parsed on a worker thread
with its own ANTLR prediction caches, and ML_PREDICT rows are built beside
inference instead of on the loop. QUERY_MAX_CONCURRENCY can cap statements
per process, refusing the excess with 429 and an audited REFUSED entry.
LLM function registration takes a Redis lock so two processes cannot drop
each other's functions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…M gateway, session-pinned agents

Follow-up to the process split, closing the gaps found in review.

Readiness: /ready answers 200 only after startup with the engine and Redis
reachable. The split stack waits on it, and the gateway retries a replica
that refuses a connection, for requests that are safe to repeat.

Load: QUERY_MAX_CONCURRENCY now defaults to 64 per process and covers
query execute and explain, the ML execution routes and MySQL proxy
statements outside a transaction. Refusals are audited and counted.

SQL CPU: the whole prepare stage of a large statement (normalise, guard,
build, pre-check, plan, fingerprint) runs on the worker pool, whose
threads use their own parser caches for any nested parse. Redaction is
remembered within a request, and fingerprinting no longer rescans the
token stream per alias. Worst event-loop stall for a 114 KB statement went
from about 1.4 s to about 0.1 s.

AI functions: AI_* bodies call an internal Nova gateway with a per-alias
token instead of embedding the provider key. The gateway adds the key,
fixes the model, and records token usage in USAGE_LLM_FUNCTIONS, shown in
AI monitoring. Matching functions are left alone at startup.

Scale-out: the gateway uses upstream groups that follow Docker DNS, pins
assistant and agent routes to one query replica per session (their consent
and cancel state is process-local), balances MySQL across proxy replicas,
and can serve HTTPS. Schema bootstrap is serialised across web replicas.
Prometheus discovers replicas through DNS in a split stack, and
check_stack gains --topology split.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With ML_TRAINING_EXECUTOR=worker, CREATE ML_MODEL and POST /ml/train queue
a job in CONFIG_ML_JOBS and wait for nova-worker, so no API process holds a
training run. The response contract is unchanged.

A job stores no credential: it names the caller's session, and the worker
trains as that user only while the same session is live with the same
principal, active role and security-context version. Otherwise the job
fails as session_expired; there is no fallback identity. The training SQL
is stored encrypted. A job no worker claims is withdrawn, a caller that
goes away cancels its job, and GET /ml/jobs/{id} shows status to the
session that queued it. Callers without a session still train locally.

Also documents the hardened split topology, and renames the new AI
monitoring source label so it no longer matches the existing "AI
Functions" option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t works

Both found by running the split stack end to end against a real engine.

Audit: every statement wrote its audit row with its own INSERT. One such
INSERT takes StarRocks about 100 ms and concurrent ones do not overlap
(about 58 a second measured), so throughput stayed near 60 statements a
second however many query replicas ran. Rows that arrive while a write is
in flight now share the next INSERT. Each caller still waits for the write
holding its own row, a lone row is written exactly as before, a refused
group is rewritten row by row, and an uncertain failure is not retried.
One query replica went from about 60 to about 135 statements a second at
48 concurrent clients.

Gateway: `hash $http_authorization consistent` did not pin anything. The
consistent variant places peers by server name, and every replica shares
one DNS name, so sessions were balanced round robin and a consent decision
reached a replica that was not running the turn. The plain hash indexes
the resolved addresses; ten of ten requests per session now reach one
replica, and an assistant turn with a consent prompt completes through
the gateway.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dwickyfp
dwickyfp merged commit a746bb5 into main Oct 14, 2026
4 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.

1 participant