Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/api/coderApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ import {
import {
ConnectionState,
ReconnectingWebSocket,
type ConnectionFailureReason,
type ConnectionProblemReason,
type ReconnectingWebSocketOptions,
type SocketFactory,
} from "../websocket/reconnectingWebSocket";
Expand Down Expand Up @@ -129,8 +129,8 @@ export class CoderApi extends Api implements vscode.Disposable {
private readonly telemetry: TelemetryReporter,
private readonly httpRequestsTelemetry: HttpRequestsTelemetry,
private readonly authConfigTracker: AuthConfigTracker,
private readonly onConnectionFailure?: (
reason: ConnectionFailureReason,
private readonly onConnectionProblem?: (
reason: ConnectionProblemReason,
route: string,
) => void,
) {
Expand All @@ -153,8 +153,8 @@ export class CoderApi extends Api implements vscode.Disposable {
token: string | undefined,
output: Logger,
telemetry: TelemetryReporter = NOOP_TELEMETRY_REPORTER,
onConnectionFailure?: (
reason: ConnectionFailureReason,
onConnectionProblem?: (
reason: ConnectionProblemReason,
route: string,
) => void,
): CoderApi {
Expand All @@ -165,7 +165,7 @@ export class CoderApi extends Api implements vscode.Disposable {
telemetry,
httpRequestsTelemetry,
authConfigTracker,
onConnectionFailure,
onConnectionProblem,
);
client.getAxiosInstance().defaults.timeout = DEFAULT_REQUEST_TIMEOUT_MS;
client.getAxiosInstance().defaults.headers.common[BAGGAGE_HEADER] =
Expand Down Expand Up @@ -565,7 +565,7 @@ export class CoderApi extends Api implements vscode.Disposable {
}
return refreshCertificates(refreshCommand, this.output);
},
onConnectionFailure: this.onConnectionFailure,
onConnectionProblem: this.onConnectionProblem,
telemetry: this.telemetry,
};

Expand Down
2 changes: 1 addition & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ async function doActivate(
deploymentSessionAuth?.token,
output,
telemetryService,
serviceContainer.getConnectionLogBuffer().onConnectionFailure,
serviceContainer.getConnectionLogBuffer().flushForConnectionProblem,
);
ctx.subscriptions.push(client);

Expand Down
10 changes: 5 additions & 5 deletions src/logging/logBuffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ const MAX_BUFFERED_CHARS = 2_000_000;
/** Entries replayed per channel call, so a flush is not one RPC per entry. */
const REPLAY_CHUNK = 100;

/** Replays buffered below-level log entries on a connection failure. */
/** Replays buffered below-level log entries on a connection problem. */
export interface ConnectionLogBuffer {
flush(reason: string, options?: { readonly retain?: boolean }): void;
readonly onConnectionFailure: (reason: string, route: string) => void;
readonly flushForConnectionProblem: (reason: string, route: string) => void;
}

interface LogEntry {
Expand Down Expand Up @@ -63,11 +63,11 @@ export class BufferingLogger implements Logger, ConnectionLogBuffer {
public readonly error = this.wrap("error");

/**
* Flush the buffer on a terminal socket failure, keyed by the
* Flush the buffer for a socket's connection problem, keyed by the
* `<reason> <route>` string Support greps for. Arrow property so it can be
* passed by value as the socket's failure callback.
* passed by value as the socket's `onConnectionProblem`.
*/
public readonly onConnectionFailure = (
public readonly flushForConnectionProblem = (
reason: string,
route: string,
): void => {
Expand Down
3 changes: 2 additions & 1 deletion src/remote/remote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,8 @@ export class Remote {
token,
this.logger,
this.serviceContainer.getTelemetryService(),
this.serviceContainer.getConnectionLogBuffer().onConnectionFailure,
this.serviceContainer.getConnectionLogBuffer()
.flushForConnectionProblem,
);
disposables.push(workspaceClient);

Expand Down
18 changes: 9 additions & 9 deletions src/websocket/reconnectingWebSocket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,10 @@ function reduceState(

export type SocketFactory<TData> = () => Promise<UnidirectionalStream<TData>>;

export type ConnectionFailureReason = ConnectionStateReason | "unreachable";
export type ConnectionProblemReason = ConnectionStateReason | "unreachable";

/** Default failure callback for callers that do not observe connection failures. */
const NOOP_CONNECTION_FAILURE = (): void => undefined;
/** Default for callers that do not observe connection problems. */
const NOOP_CONNECTION_PROBLEM = (): void => undefined;

/**
* Consecutive failed reconnect attempts before the buffer is flushed once and
Expand All @@ -135,8 +135,8 @@ export interface ReconnectingWebSocketOptions {
* Callback invoked on a terminal failure, or once per outage when the server
* stays unreachable. Retrying continues in the unreachable case.
*/
onConnectionFailure?: (
reason: ConnectionFailureReason,
onConnectionProblem?: (
reason: ConnectionProblemReason,
route: string,
) => void;
}
Expand Down Expand Up @@ -206,8 +206,8 @@ export class ReconnectingWebSocket<
maxBackoffMs: options.maxBackoffMs ?? 30000,
jitterFactor: options.jitterFactor ?? 0.1,
onCertificateRefreshNeeded: options.onCertificateRefreshNeeded,
onConnectionFailure:
options.onConnectionFailure ?? NOOP_CONNECTION_FAILURE,
onConnectionProblem:
options.onConnectionProblem ?? NOOP_CONNECTION_PROBLEM,
};
this.#lastRoute = options.route;
this.#backoffMs = this.#options.initialBackoffMs;
Expand Down Expand Up @@ -332,7 +332,7 @@ export class ReconnectingWebSocket<
});
this.clearCurrentSocket(options.code, options.closeReason);
if (options.failure) {
this.#options.onConnectionFailure(reason, this.#route);
this.#options.onConnectionProblem(reason, this.#route);
}
}

Expand Down Expand Up @@ -477,7 +477,7 @@ export class ReconnectingWebSocket<
this.#route,
this.#consecutiveConnectFailures,
);
this.#options.onConnectionFailure("unreachable", this.#route);
this.#options.onConnectionProblem("unreachable", this.#route);
}
const jitter =
this.#backoffMs * this.#options.jitterFactor * (Math.random() * 2 - 1);
Expand Down
2 changes: 1 addition & 1 deletion test/mocks/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ export function createMockServiceContainer(
getLogger: () => logger,
getConnectionLogBuffer: (): ConnectionLogBuffer => ({
flush: () => {},
onConnectionFailure: () => {},
flushForConnectionProblem: () => {},
}),
getSecretsManager: () =>
require("secretsManager", overrides.secretsManager),
Expand Down
20 changes: 10 additions & 10 deletions test/unit/api/coderApi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ describe("CoderApi", () => {
url = CODER_URL,
token = AXIOS_TOKEN,
telemetry: TelemetryReporter = NOOP_TELEMETRY_REPORTER,
onConnectionFailure?: (reason: string) => void,
onConnectionProblem?: (reason: string) => void,
) => {
return CoderApi.create(
url,
token,
mockLogger,
telemetry,
onConnectionFailure,
onConnectionProblem,
);
};

Expand Down Expand Up @@ -577,14 +577,14 @@ describe("CoderApi", () => {
});
});

describe("connection failure callback", () => {
it("invokes onConnectionFailure on a terminal socket failure", async () => {
const onConnectionFailure = vi.fn();
describe("connection problem callback", () => {
it("invokes onConnectionProblem on a terminal socket failure", async () => {
const onConnectionProblem = vi.fn();
const failingApi = createApi(
CODER_URL,
AXIOS_TOKEN,
NOOP_TELEMETRY_REPORTER,
onConnectionFailure,
onConnectionProblem,
);
const mockWs = createMockWebSocket(
`wss://${CODER_URL.replace("https://", "")}/api/v2/workspaceagents/${AGENT_ID}/watch-metadata-ws`,
Expand All @@ -600,7 +600,7 @@ describe("CoderApi", () => {
wasClean: false,
});

expect(onConnectionFailure).toHaveBeenCalledWith(
expect(onConnectionProblem).toHaveBeenCalledWith(
"unrecoverable_close",
`/api/v2/workspaceagents/${AGENT_ID}/watch-metadata-ws`,
);
Expand Down Expand Up @@ -675,12 +675,12 @@ describe("CoderApi", () => {
});

it("treats an HTTP failure of the SSE fallback as unrecoverable", async () => {
const onConnectionFailure = vi.fn();
const onConnectionProblem = vi.fn();
api = createApi(
CODER_URL,
AXIOS_TOKEN,
NOOP_TELEMETRY_REPORTER,
onConnectionFailure,
onConnectionProblem,
);
setupWebSocketMock(
createMockWebSocket("wss://test", {
Expand All @@ -700,7 +700,7 @@ describe("CoderApi", () => {

const connection = await api.watchAgentMetadata(AGENT_ID);

expect(onConnectionFailure).toHaveBeenCalledWith(
expect(onConnectionProblem).toHaveBeenCalledWith(
"unrecoverable_http",
`/api/v2/workspaceagents/${AGENT_ID}/watch-metadata-ws`,
);
Expand Down
2 changes: 1 addition & 1 deletion test/unit/commands.telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ function setup(options: SetupOptions = {}) {
getNetcheckPanelFactory: () => ({}) as NetcheckPanelFactory,
getConnectionLogBuffer: (): ConnectionLogBuffer => ({
flush: () => {},
onConnectionFailure: () => {},
flushForConnectionProblem: () => {},
}),
} as ServiceContainer;

Expand Down
Loading
Loading