e5acc75f9efa

end the bundle with 'end 0' so a cut connection is caught; tests pinned to koh 3.4.1 (v3.0.212)

time
2026-10-03 17:47 UTC · 1 week ago
machine
Junes-MacBook-Pro.local
agent
claude-opus-5-5
session
faster whole-repo steal
parent
7653310330f2
4 files package.json+1 −1src/mirror/remote.ts+6 −1tests/koh-version.txt+1 −1tests/kohremote.test.ts+2 −0
package.json+1 −1
@@ -1,6 +1,6 @@11 {22 	"name": "kepr",3-	"version": "3.0.211",3+	"version": "3.0.212",44 	"private": true,55 	"type": "module",66 	"scripts": {

view file

src/mirror/remote.ts+6 −1
@@ -184,7 +184,10 @@184184 	});185185 }186186 187-/** Each entry is `<key> <length>\n` and then that many bytes, keyed as the single routes are. */187+/**188+ * Each entry is `<key> <length>\n` and then that many bytes, keyed as the single routes are, and189+ * the last line is `end 0`.190+ */188191 function* bundle(mirror: Database): Generator<Uint8Array> {189192 	const encoder = new TextEncoder();190193 	function* entry(key: string, bytes: Uint8Array): Generator<Uint8Array> {@@ -202,6 +205,8 @@202205 		WHERE EXISTS (SELECT 1 FROM save_files f WHERE f.hash = o.hash)`,203206 	);204207 	for (const row of objects.iterate()) yield* entry(`objects/${row.hash}`, row.data);208+	// A connection cut between two entries would otherwise pass for the whole repo.209+	yield encoder.encode("end 0\n");205210 }206211 207212 // Field names and their order are Koh's, and every optional is an empty string, as `json2.encode`

view file

tests/koh-version.txt+1 −1
@@ -1 +1 @@1-3.4.01+3.4.1

view file

tests/kohremote.test.ts+2 −0
@@ -149,6 +149,8 @@149149 			...(await listed("events")),150150 			...(await listed("objects")),151151 		];152+		expect(new TextDecoder().decode(body.subarray(body.length - 6))).toBe("end 0\n");153+		entries.delete("end");152154 		expect([...entries.keys()].sort()).toEqual(keys.sort());153155 		for (const key of keys) {154156 			const single = new Uint8Array(await (await get(key)).arrayBuffer());

view file