Run imports and deletes on the server, and say so on an event
Leaving the import screen used to cancel the batch it had started: the
request was the work, so the coroutine that owned it died with the screen
and coming back showed no sign anything had happened. A half-imported
session is the expensive kind of missing -- the row is back looking
untouched, and taking it again is the second `--resume` the import path
exists to prevent.
So the work runs on the server now. Delete and a new per-session import both
answer 202 and spawn the work, and `session::pending` is the record of it:
what is running, and how the last attempt failed. The phone reads that two
ways and needs both. Every row of the listing carries `pending` and `error`,
which is what a phone that was asleep, out of range or freshly opened has to
go on; `GET /setups/{id}/importable/events` streams the changes, which is
what makes a screen somebody is watching change by itself.
Neither alone is enough, and that is not theoretical. A broadcast has no
memory, so an operation that started and finished while the stream was still
connecting was one nothing would ever be said about -- with responses held
back far enough to make it visible, one row of a pair of deletes cleared and
the other sat on "waiting" for good. The screen now asks again after a
handover when anything still looks outstanding, and takes its row states
from that answer rather than from what it remembers.
The single tap still waits, because "take me to it" needs the session that
was made and 202 does not carry one. Both paths go through the same `spawn`
so they cannot drift about what importing means.
Resolving one importable session no longer lists every one of them:
`import::find` is the same script with one glob narrower, which takes the
import seed off the 3.7-second full scan that `delete` came off earlier.
The SSE connection and its framing are now `Sse`, shared with the session
transcript stream rather than written a second time.
This commit is contained in:
1 parent
b172c464ea
commit
3c159fa1e1
12 files changed
+992
-176
No files matched your search
@@ -209,6 +209,22 @@ first if a remote spawn ever mangles an argument.
|
||||
word rather than a bare spinner because "deleting" and "importing" differ
|
||||
in kind, and the inertness is the overlay consuming pointer events rather
|
||||
than each caller remembering to disable its own click handler.
|
||||
- **Importing and deleting run on the server, not in the request.** `DELETE
|
||||
/setups/{id}/importable/{session}` and `POST
|
||||
/setups/{id}/importable/{session}/import` both answer 202 and do the work
|
||||
in a spawned task, because the phone that asked is free to leave and used
|
||||
to cancel its own batch by doing so. What replaces the reply is
|
||||
`session::pending`: every row of the listing carries `pending` and
|
||||
`error`, and `GET /setups/{id}/importable/events` streams the changes.
|
||||
**Both, not either.** The stream is a broadcast with no memory, so an
|
||||
operation that starts and finishes while it is still connecting is one
|
||||
nothing will ever be said about -- that left a row marked "waiting" for
|
||||
ever, and the listing is what repairs it. So the screen fetches again
|
||||
after a handover when anything still looks outstanding, and takes the row
|
||||
states from the answer rather than from what it remembers.
|
||||
- **A single tap still waits.** "Continue this and take me to it" needs the
|
||||
session it made, and 202 does not carry one. The batch and the tap share
|
||||
`spawn` on the server so the two cannot drift about what importing means.
|
||||
- **The import screen selects in batches: hold to enter, tap to add.** The
|
||||
options that act on a selection appear along the bottom, and are Delete
|
||||
and Import only. Submitting clears the selection immediately and marks
|
||||
@@ -271,7 +287,12 @@ first if a remote spawn ever mangles an argument.
|
||||
real `--resume` on the owner's account. Neither is a price worth paying to
|
||||
look at a list. It shares the real TLS certificates, because the
|
||||
installed APK pins that CA, so run it while the ordinary server is down.
|
||||
It passes `--delay` by default for the reason the next entry gives.
|
||||
It passes `--delay` by default for the reason the next entry gives, and
|
||||
`AI_SANDBOX_BIG_MB` puts one large transcript among the small ones --
|
||||
`AI_SANDBOX_SPAWN_DELAY` makes the fake CLI slow to start. Both exist
|
||||
because operations that finish in milliseconds have states on the way that
|
||||
nothing can observe, and an unobservable state is one where broken and
|
||||
working look identical.
|
||||
- **`ai-server --delay MS` holds every response back.** Over the tunnel a
|
||||
phone's requests take tens to hundreds of milliseconds, and several
|
||||
faults live entirely in what the app does *while* one is outstanding. On
|
||||
@@ -522,6 +543,14 @@ machine belongs in `~/.claude/TOOLCHAIN.md` (toolchain versions) or
|
||||
perfectly -- while the usage dialog, reading the same field, quietly drew
|
||||
nothing. `WindowEnd` in `ResetCountdown.kt` is now the one rule both go
|
||||
through.
|
||||
- **Resolving one importable session used to list every one of them.**
|
||||
`import::delete` and the import seed both called `list`, which reads every
|
||||
transcript Claude Code has ever written -- measured at 3.7 seconds against
|
||||
the 867 MB in this VM, paid once per session in a batch. `import::find`
|
||||
takes the same script with one glob narrower, and `delete` resolves the
|
||||
path itself: 78ms. Ids are checked (`is_session_id`) before they reach
|
||||
that glob, since a `/` or `..` in one walks it out of the projects
|
||||
directory and `delete` removes what it lands on.
|
||||
- **A transcript page used to cost the whole transcript.** `read_window`
|
||||
read and parsed every line and then kept the last `limit` of them, so the
|
||||
work was the size of the conversation rather than the size of the answer:
|
||||
|
||||
Reference in new issue
Block a user