feat(rpc): configurable RPC init timeout via SF_RPC_INIT_TIMEOUT_MS
Add resolveRpcInitTimeoutMs() helper and wire it into RpcClient.init(). Default init timeout increased from 30s to 120s. Override via env var. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
ced90e84a8
commit
e2e096c5c7
2 changed files with 35 additions and 7 deletions
|
|
@ -36,6 +36,14 @@ type DistributiveOmit<T, K extends keyof T> = T extends unknown
|
|||
|
||||
/** RpcCommand without the id field (for internal send) */
|
||||
type RpcCommandBody = DistributiveOmit<RpcCommand, "id">;
|
||||
const DEFAULT_RPC_REQUEST_TIMEOUT_MS = 30_000;
|
||||
const DEFAULT_RPC_INIT_TIMEOUT_MS = 120_000;
|
||||
|
||||
export function resolveRpcInitTimeoutMs(): number {
|
||||
const parsed = Number.parseInt(process.env.SF_RPC_INIT_TIMEOUT_MS ?? "", 10);
|
||||
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
||||
return DEFAULT_RPC_INIT_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
export interface RpcClientOptions {
|
||||
/** Path to the CLI entry point (default: searches for dist/cli.js) */
|
||||
|
|
@ -635,11 +643,14 @@ export class RpcClient {
|
|||
* Returns the negotiated protocol version, session ID, and server capabilities.
|
||||
*/
|
||||
async init(options?: { clientId?: string }): Promise<RpcInitResult> {
|
||||
const response = await this.send({
|
||||
type: "init",
|
||||
protocolVersion: 2,
|
||||
clientId: options?.clientId,
|
||||
});
|
||||
const response = await this.send(
|
||||
{
|
||||
type: "init",
|
||||
protocolVersion: 2,
|
||||
clientId: options?.clientId,
|
||||
},
|
||||
resolveRpcInitTimeoutMs(),
|
||||
);
|
||||
return this.getData<RpcInitResult>(response);
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +776,10 @@ export class RpcClient {
|
|||
}
|
||||
}
|
||||
|
||||
private async send(command: RpcCommandBody): Promise<RpcResponse> {
|
||||
private async send(
|
||||
command: RpcCommandBody,
|
||||
timeoutMs = DEFAULT_RPC_REQUEST_TIMEOUT_MS,
|
||||
): Promise<RpcResponse> {
|
||||
if (!this.process?.stdin) {
|
||||
throw new Error("Client not started");
|
||||
}
|
||||
|
|
@ -781,7 +795,7 @@ export class RpcClient {
|
|||
`Timeout waiting for response to ${command.type}. Stderr: ${this.stderr}`,
|
||||
),
|
||||
);
|
||||
}, 30000);
|
||||
}, timeoutMs);
|
||||
|
||||
this.pendingRequests.set(id, {
|
||||
resolve: (response) => {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import { attachJsonlLineReader, serializeJsonLine } from "./jsonl.js";
|
|||
import {
|
||||
buildRpcLaunchSpec,
|
||||
collectRpcDescendantPids,
|
||||
resolveRpcInitTimeoutMs,
|
||||
shouldDetachRpcChild,
|
||||
signalRpcProcessTree,
|
||||
} from "./rpc-client.js";
|
||||
|
|
@ -451,6 +452,19 @@ describe("RpcClient command serialization", () => {
|
|||
assert.equal(parsed.clientId, "test-client");
|
||||
});
|
||||
|
||||
it("init timeout defaults longer than normal request timeout", () => {
|
||||
assert.equal(resolveRpcInitTimeoutMs(), 120_000);
|
||||
});
|
||||
|
||||
it("init timeout can be overridden by env", () => {
|
||||
process.env.SF_RPC_INIT_TIMEOUT_MS = "45000";
|
||||
try {
|
||||
assert.equal(resolveRpcInitTimeoutMs(), 45_000);
|
||||
} finally {
|
||||
delete process.env.SF_RPC_INIT_TIMEOUT_MS;
|
||||
}
|
||||
});
|
||||
|
||||
it("shutdown command serializes correctly", () => {
|
||||
const cmd = { id: "req_2", type: "shutdown" };
|
||||
const serialized = serializeJsonLine(cmd);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue