Search and scrollback export no longer reach the browser #1

Open
opened 2026-09-07 20:53:19 +09:00 by natsukium · 0 comments
Owner

Search and scrollback export no longer reach the browser

What changed under us

Until felis 32775067 the search and capture verbs rode the Input family, so they needed
no channel of their own: the browser sent {"Search": …} / {"CaptureScrollback": …} down
the same socket as a keystroke, and the answers came back as GridMsg::SearchMatch,
SearchDone, ScrollbackRow, ScrollbackDone and CaptureRegion.

At 105b089979369fd310757375af3df7900ae7e523 none of those variants exist. Search is the
Search family and capture is Region, both correlated: a request carries a
stream_id allocated from the connection's driver, and every reply and stream terminal names
it back. A request with no envelope is not ignored — the daemon ends the connection over it
(reproduced in natsukium/felis#196).

Why the gateway cannot forward them today

serve() and broker::open_stream() both destructure the connection after the attach:

let Connection { reader, writer, .. } = conn;

so the reader task and the writer task can run concurrently — and the driver that allocates
stream ids, tracks the open ones, and classifies the frames that answer them is dropped on
that line. Nothing is left to allocate from, so neither family is routed in either direction.
The relay is otherwise unaffected: the grid stream, input, resize, theme and the roster verbs
are all uncorrelated or go through Connection's own helpers.

What it costs

<felis-terminal>'s search bar and its scrollback export have no server behind them over a
gateway connection. Nothing errors — the browser sends a frame that no longer parses as an
InputMsg and the gateway drops it with a stderr line, so the feature is silently inert.

What a fix has to face

The driver is one per connection and is &mut on every classify. Splitting a connection into
a reader task and a writer task is what makes it unshareable, so the fix is a shape decision,
not a patch:

  • keep the whole connection in one task and drive both directions from a select! (the
    relay task already has that shape — it is the Connection split that is the problem);
  • or hold the driver behind a mutex the two tasks share, paying a lock per frame on the hot
    grid path;
  • or run search/capture on a second, short-lived daemon connection per request, the way
    the ops verbs already work — which costs a dial but keeps the streaming path untouched and
    needs no lock. Region/Search are admitted to an Ops connection, and capture there
    reads the session through the reply rather than through an attach burst.

The third is probably the answer, and it also gives the broker a natural request shape
({"req": n, "op": {"search": {…}}}) instead of an out-of-band frame on a sid.

Deferred out of the felis 105b0899 follow because it is a feature restoration with a design
choice in it, not part of making the relay build and stream again.

Search and scrollback export no longer reach the browser ## What changed under us Until felis `32775067` the search and capture verbs rode the `Input` family, so they needed no channel of their own: the browser sent `{"Search": …}` / `{"CaptureScrollback": …}` down the same socket as a keystroke, and the answers came back as `GridMsg::SearchMatch`, `SearchDone`, `ScrollbackRow`, `ScrollbackDone` and `CaptureRegion`. At `105b089979369fd310757375af3df7900ae7e523` none of those variants exist. Search is the `Search` family and capture is `Region`, both **correlated**: a request carries a `stream_id` allocated from the connection's driver, and every reply and stream terminal names it back. A request with no envelope is not ignored — the daemon ends the connection over it (reproduced in natsukium/felis#196). ## Why the gateway cannot forward them today `serve()` and `broker::open_stream()` both destructure the connection after the attach: ```rust let Connection { reader, writer, .. } = conn; ``` so the reader task and the writer task can run concurrently — and the `driver` that allocates stream ids, tracks the open ones, and classifies the frames that answer them is dropped on that line. Nothing is left to allocate from, so neither family is routed in either direction. The relay is otherwise unaffected: the grid stream, input, resize, theme and the roster verbs are all uncorrelated or go through `Connection`'s own helpers. ## What it costs `<felis-terminal>`'s search bar and its scrollback export have no server behind them over a gateway connection. Nothing errors — the browser sends a frame that no longer parses as an `InputMsg` and the gateway drops it with a stderr line, so the feature is silently inert. ## What a fix has to face The driver is one per connection and is `&mut` on every classify. Splitting a connection into a reader task and a writer task is what makes it unshareable, so the fix is a shape decision, not a patch: - keep the whole connection in one task and drive both directions from a `select!` (the relay task already has that shape — it is the `Connection` split that is the problem); - or hold the driver behind a mutex the two tasks share, paying a lock per frame on the hot grid path; - or run search/capture on a **second, short-lived daemon connection** per request, the way the ops verbs already work — which costs a dial but keeps the streaming path untouched and needs no lock. `Region`/`Search` are admitted to an `Ops` connection, and `capture` there reads the session through the reply rather than through an attach burst. The third is probably the answer, and it also gives the broker a natural request shape (`{"req": n, "op": {"search": {…}}}`) instead of an out-of-band frame on a `sid`. Deferred out of the felis `105b0899` follow because it is a feature restoration with a design choice in it, not part of making the relay build and stream again.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
natsukium/felis-web-gateway#1
No description provided.