Delete a batch of imports in one command, not one connection each

Replaces the connection throttle from the previous commit, which was a
workaround: it made a batch slower without changing that N sessions
meant N ssh connections, and the cap it picked was a guess at somebody
else's sshd config.

The batch now goes out as a single invocation. import::delete takes the
whole list, the remote script loops over the ids and prints one
`<id>\t<state>` line each, and the route settles every row from its own
line. So a batch of any size is one connection and cannot exceed
MaxStartups however many rows are selected -- and it is faster, since
it stopped paying a handshake per session.

Each id still reports on its own: deleted, missing, or failed, kept
apart because only "failed" is worth retrying. Ids the machine never
mentioned -- a connection that dropped part-way -- are reported as
unknown rather than defaulting to either answer, and a malformed id
fails only itself.

Verified end-to-end against a fake ssh that counts connections: a
9-session batch used one, every row settled, both copies of a session
recorded under two project directories went, and the id that was not
there failed with a message saying so rather than a connection error.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
irisandClaude Opus 5 committed 2026-09-01 00:32:52 -04:00
1 parent 7a1a462caf
commit dce1799802
4 files changed
+230 -79

No files matched your search

-7
View File
@@ -163,13 +163,6 @@ pub fn tidy(value: &str) -> Option<String> {
/// Runs a launch to completion and returns its stdout.
impl Transport {
pub async fn capture(&self, launch: &Launch) -> Result<String> {
// See `CAPTURE_PERMITS`: caps how many of these run their ssh
// connection at once, so a batch doesn't open more than the remote
// sshd tolerates before it starts dropping them.
let _permit = super::session::transport::CAPTURE_PERMITS
.acquire()
.await
.expect("capture semaphore is never closed");
let child = self.spawn(launch, super::session::transport::Streams::Piped)?;
let output = child
.wait_with_output()