Repository navigation
Conversation
jsam
force-pushed
the
fm/il-w02
branch
2 times, most recently
from
October 3, 2026 19:02
6768982 to
6b5f88c
Compare
Each /ws connection is one loop that owns its read half, the single writer, its subscriptions and a bounded request pipeline. Requests run as pipeline tasks, so a long query no longer holds up the connection's notifications and subscription deltas. - Programs made only of queries overlap; writes, rules, session changes, KG switches and subscription commands run alone, in order, so a pipelined insert after .kg use always lands on the new KG. - Replies are released in request order (no request IDs needed). - At most http.rate_limit.ws_max_in_flight_requests (default 16) requests are unanswered; at the bound the loop stops reading. - .subscribe evaluates its snapshot off the loop; commits landing meanwhile are recorded and re-evaluated after registration. - Disconnect aborts running queries and lets a started write finish. Tests: pipeline unit tests, in-process ws_pipeline_tests (500 ms+ query with concurrent delta, KG switch + insert ordering, disconnect cleanup, bounded pipeline, saturated mixed traffic) and a required e2e_reactive scenario; the testkit client learns pipelined requests. Includes perf(ws): poll requests in the connection task and keep one idle timer: Requests were spawned as tasks; a woken idle worker would steal each one, so every request crossed cores twice. They are now futures owned by the pipeline and polled by the connection loop; computation already runs on the blocking pool, and results over 256 rows are serialized there too, so nothing heavy runs on the loop. A panic is caught per request and released as an internal error. The idle timeout used to be a freshly boxed timer every loop turn; it is now one pinned timer reset on activity, armed only while no request is pending (covered by a new test). perf gate, cheap_query vs fm/il-rc1, 20 rounds: latency p50 1.034 (1.014..1.045), p99 1.015, qps 1.009, all PASS. Rebased onto main with W01 request IDs and W04 revision-tagged subscriptions: a .subscribe pushes the snapshot's revision, and registration both replays changes recorded during the snapshot and re-evaluates when the knowledge graph moved past the snapshot's revision.
Contributor
Author
|
Superseded by #214, which carries these W02 commits rebased onto main. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Draft for visibility. Stacked on the release checkpoint 1 branch (
fm/il-rc1); it will be retargeted tomainonce checkpoint 1 lands. Plan item W02 (partial #132).What it does
Each
/wsconnection becomes one loop that owns its read half, the single writer, its subscriptions and a bounded request pipeline. Requests run as pipeline tasks, so a long query no longer holds up the connection's notifications and subscription deltas..kg …,.session …,.subscribe/.unsubscribeand other meta commands run alone and in order. A pipelined insert sent after.kg use otheralways lands inother.http.rate_limit.ws_max_in_flight_requests(default 16) requests can be unanswered at once; at that bound the loop stops reading the socket..subscribeevaluates its snapshot in a task. Commits that land meanwhile are recorded and re-evaluated after registration, so no delta is lost.Docs: WebSocket guide, AsyncAPI spec, configuration reference, TESTING.md.
Tests
tests/ws_pipeline_tests.rs, in-process:e2e_reactivescenario: an agent receives deltas while its own long query runs (release; writer ack to delta ≤250 ms).Performance
Depends on
TCP_NODELAYfrom #200. Because pushes now go out while a request runs, a writer's ownpersistent_updateoften precedes its reply. Under Nagle that delays the write ack by ~40 ms (perf gate: insert ack p50 10.6 → 43 ms without it).Requests are futures polled by the connection task (no task per request); results over 256 rows are serialized on the blocking pool; the idle timeout is one pinned timer.
Perf gate vs
fm/il-rc1, final code with #200's change applied, 10 rounds: no FAIL, 15 required metrics PASS and 5 INCONCLUSIVE. The INCONCLUSIVE point estimates are ≤ 1.014; their intervals straddle the budget from noise.cheap_query(20 rounds): p50 1.034 (1.014..1.045), p99, qps and concurrent all PASS.Also run:
make test-fast,make e2e-reactive(11/11), full.iql.outsnapshot suite (1149/1149, also as a 96-worker stress run),make oracle-test.Tracker: #199