Swimlane view: compare streams side by side in the browser#1957
Merged
Conversation
A browser extension comparing several streams side by side: their events merged into one newest-first timeline table, one column per stream, with infinite scroll and a created-at/valid-at sort toggle. An event linked into several compared streams renders once, as a link in each matching column. Each page is composed from existing single-stream reads - one time ordered read per compared stream, k-way merged by event time. Count is the read depth per stream, not the page size: a page emits everything above the completeness horizon (the highest chunk end among the streams whose read was cut), so nothing provably complete is thrown away. The shared cursor is that horizon timestamp and the next page asks for strictly older events - nothing is dropped or repeated. Built entirely on the browser extension API: routes and json responses via register_routes, an entry link via stream_links, its own stimulus controllers via scripts.
The feature moves from the ruby_event_store-browser-swimlane contrib gem into ruby_event_store-browser itself, available out of the box with no configuration. The /swimlane and /swimlane/more routes are served by App, the views live under views/swimlane, the url builders on Urls, the stimulus controllers ship in the main js bundle and the stream page always offers a Streamline entry link, followed by any extension-contributed links. The extension API stays intact - only its swimlane consumer is gone, together with the contrib gem and its CI workflows. Specs follow into the browser suite; new Urls and App subjects are mutation-covered.
pjurewicz
force-pushed
the
browser-swimlane-builtin
branch
from
July 22, 2026 16:52
d51f99b to
ce6b542
Compare
pjurewicz
marked this pull request as ready for review
July 22, 2026 16:52
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.
Supersedes #1955 — same feature, but built directly into
ruby_event_store-browserinstead of shipping as aruby_event_store-browser-swimlanecontrib gem. Zero configuration: mount the browser and it's there.What it does
A swimlane view comparing several streams side by side: their events merged into one newest-first timeline table, one column per stream, with infinite scroll and a created-at/valid-at sort toggle. An event linked into several compared streams renders once, as a link in each matching column. Streams can be added and removed from the comparison in place; every non-global stream page links to its swimlane view.
How it reads
Each page is composed from existing single-stream reads — one time-ordered read per compared stream, k-way merged by event time. Count is the read depth per stream, not the page size: a page emits everything above the completeness horizon (the highest chunk end among the streams whose read was cut), so nothing provably complete is thrown away. The shared cursor is that horizon timestamp and the next page asks for strictly older events — nothing is dropped or repeated.
Browser changes
GET /swimlaneandGET /swimlane/moreserved byApp, views underviews/swimlane, url builders onUrls, Stimulus controllers in the main js bundle.register_routes,stream_links,stylesheets,scripts, json/partial responses) introduced earlier in this branch stays — the swimlane no longer consumes it, but extensions can.UrlsandAppcode is mutation-covered.