mirror of
https://github.com/Kilo-Org/kilocode.git
synced 2026-11-03 22:58:59 +08:00
Completes #12999 (with the fixture change in the previous commit). Adds --shard <i>/<n> (round-robin scenario subset) and --shards <n> (spawns n child processes, each with its own PID-keyed database and global root, tagged output, combined exit code). test:httpapi runs the effect pass with --shards 2. Route coverage (missing/extra) is still computed against the full scenario list in every child, so --fail-on-missing stays correct. Local effect-mode wall clock: 4m11s -> 2m39s (6m37s before this PR). 315/315 scenarios pass across both shards.
46 lines
1.9 KiB
TypeScript
46 lines
1.9 KiB
TypeScript
// kilocode_change start - `--shards N` fans a pass out across N child processes, each
|
|
// running `--shard i/N`. Children are fully isolated: the exerciser keys its database
|
|
// and global root by PID (test/server/httpapi-exercise/environment.ts), so shards never
|
|
// share SQLite files or on-disk state. Route coverage (missing/extra) stays correct
|
|
// because every child checks it against the full scenario list.
|
|
const args = Bun.argv.slice(2)
|
|
const shardsIndex = args.indexOf("--shards")
|
|
const shards = shardsIndex === -1 ? 0 : Number(args[shardsIndex + 1])
|
|
|
|
if (shardsIndex !== -1 && (!Number.isInteger(shards) || shards < 1)) {
|
|
console.error(`invalid --shards ${args[shardsIndex + 1]}, expected a positive integer`)
|
|
process.exit(1)
|
|
}
|
|
|
|
if (shards > 1) {
|
|
const passthrough = args.filter((_, index) => index !== shardsIndex && index !== shardsIndex + 1)
|
|
const children = Array.from({ length: shards }, (_, index) =>
|
|
Bun.spawn(
|
|
[process.execPath, "run", import.meta.path, ...passthrough, "--shard", `${index + 1}/${shards}`],
|
|
{ stdout: "pipe", stderr: "pipe" },
|
|
),
|
|
)
|
|
const relay = async (stream: ReadableStream<Uint8Array>, tag: string, sink: NodeJS.WriteStream) => {
|
|
const decoder = new TextDecoder()
|
|
let buffer = ""
|
|
for await (const chunk of stream) {
|
|
buffer += decoder.decode(chunk, { stream: true })
|
|
const lines = buffer.split("\n")
|
|
buffer = lines.pop() ?? ""
|
|
for (const line of lines) sink.write(`${tag} ${line}\n`)
|
|
}
|
|
if (buffer) sink.write(`${tag} ${buffer}\n`)
|
|
}
|
|
const codes = await Promise.all(
|
|
children.map(async (child, index) => {
|
|
const tag = `[shard ${index + 1}/${shards}]`
|
|
await Promise.all([relay(child.stdout, tag, process.stdout), relay(child.stderr, tag, process.stderr)])
|
|
return child.exited
|
|
}),
|
|
)
|
|
process.exit(codes.every((code) => code === 0) ? 0 : 1)
|
|
}
|
|
// kilocode_change end
|
|
|
|
await import("../test/server/httpapi-exercise/index")
|