refactor: move daemon registry into host-runtime store
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { type HostConnection } from "@/contexts/daemon-registry-context";
|
||||
import type { HostConnection } from "@/types/host-connection";
|
||||
import {
|
||||
selectBestConnection,
|
||||
type ConnectionCandidate,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { HostConnection } from "@/contexts/daemon-registry-context";
|
||||
import type { HostConnection } from "@/types/host-connection";
|
||||
|
||||
export type ConnectionCandidate = {
|
||||
connectionId: string;
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import { getTauri } from "@/utils/tauri";
|
||||
|
||||
let attached = false;
|
||||
|
||||
export function attachConsole(): void {
|
||||
if (attached || !getTauri()) {
|
||||
return;
|
||||
}
|
||||
attached = true;
|
||||
|
||||
const originalLog = console.log;
|
||||
const originalInfo = console.info;
|
||||
const originalWarn = console.warn;
|
||||
const originalError = console.error;
|
||||
const originalDebug = console.debug;
|
||||
|
||||
function formatArgs(args: unknown[]): string {
|
||||
return args
|
||||
.map((a) =>
|
||||
typeof a === "string" ? a : JSON.stringify(a, null, 0) ?? String(a)
|
||||
)
|
||||
.join(" ");
|
||||
}
|
||||
|
||||
function forwardToRust(level: number, args: unknown[]): void {
|
||||
const invoke = getTauri()?.core?.invoke;
|
||||
if (typeof invoke !== "function") return;
|
||||
try {
|
||||
void invoke("webview_log", { level, message: formatArgs(args) });
|
||||
} catch {
|
||||
// silently ignore IPC errors
|
||||
}
|
||||
}
|
||||
|
||||
console.log = (...args: unknown[]) => {
|
||||
originalLog.apply(console, args);
|
||||
forwardToRust(0, args); // debug
|
||||
};
|
||||
console.info = (...args: unknown[]) => {
|
||||
originalInfo.apply(console, args);
|
||||
forwardToRust(1, args); // info
|
||||
};
|
||||
console.warn = (...args: unknown[]) => {
|
||||
originalWarn.apply(console, args);
|
||||
forwardToRust(2, args); // warn
|
||||
};
|
||||
console.error = (...args: unknown[]) => {
|
||||
originalError.apply(console, args);
|
||||
forwardToRust(3, args); // error
|
||||
};
|
||||
console.debug = (...args: unknown[]) => {
|
||||
originalDebug.apply(console, args);
|
||||
forwardToRust(0, args); // debug
|
||||
};
|
||||
}
|
||||
@@ -60,40 +60,44 @@ vi.mock("./client-id", () => ({
|
||||
getOrCreateClientId: clientIdMock.getOrCreateClientId,
|
||||
}));
|
||||
|
||||
describe("test-daemon-connection probe client identity", () => {
|
||||
describe("test-daemon-connection connectToDaemon", () => {
|
||||
beforeEach(() => {
|
||||
daemonClientMock.createdConfigs.length = 0;
|
||||
clientIdMock.getOrCreateClientId.mockClear();
|
||||
});
|
||||
|
||||
it("reuses the app clientId for direct latency probes", async () => {
|
||||
it("reuses the app clientId for direct connections", async () => {
|
||||
const mod = await import("./test-daemon-connection");
|
||||
|
||||
await mod.measureConnectionLatency({
|
||||
id: "direct:lan:6767",
|
||||
type: "directTcp",
|
||||
endpoint: "lan:6767",
|
||||
});
|
||||
await mod.measureConnectionLatency({
|
||||
const first = await mod.connectToDaemon({
|
||||
id: "direct:lan:6767",
|
||||
type: "directTcp",
|
||||
endpoint: "lan:6767",
|
||||
});
|
||||
await first.client.close();
|
||||
|
||||
const [first, second] = daemonClientMock.createdConfigs;
|
||||
expect(first?.clientId).toBe("cid_shared_probe_test");
|
||||
expect(second?.clientId).toBe("cid_shared_probe_test");
|
||||
const second = await mod.connectToDaemon({
|
||||
id: "direct:lan:6767",
|
||||
type: "directTcp",
|
||||
endpoint: "lan:6767",
|
||||
});
|
||||
await second.client.close();
|
||||
|
||||
const [firstConfig, secondConfig] = daemonClientMock.createdConfigs;
|
||||
expect(firstConfig?.clientId).toBe("cid_shared_probe_test");
|
||||
expect(secondConfig?.clientId).toBe("cid_shared_probe_test");
|
||||
expect(clientIdMock.getOrCreateClientId).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("encodes the local socket target into the probe client config", async () => {
|
||||
it("encodes the local socket target into the client config", async () => {
|
||||
const mod = await import("./test-daemon-connection");
|
||||
|
||||
await mod.measureConnectionLatency({
|
||||
const result = await mod.connectToDaemon({
|
||||
id: "socket:/tmp/paseo.sock",
|
||||
type: "directSocket",
|
||||
path: "/tmp/paseo.sock",
|
||||
});
|
||||
await result.client.close();
|
||||
|
||||
expect(daemonClientMock.createdConfigs[0]?.url).toBe(
|
||||
"paseo+local://socket?path=%2Ftmp%2Fpaseo.sock"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { DaemonClient } from "@server/client/daemon-client";
|
||||
import type { DaemonClientConfig } from "@server/client/daemon-client";
|
||||
import type { HostConnection } from "@/contexts/daemon-registry-context";
|
||||
import type { HostConnection } from "@/types/host-connection";
|
||||
import { getOrCreateClientId } from "./client-id";
|
||||
import { buildDaemonWebSocketUrl, buildRelayWebSocketUrl } from "./daemon-endpoints";
|
||||
import {
|
||||
@@ -45,7 +45,7 @@ export class DaemonConnectionTestError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
async function buildClientConfig(
|
||||
export async function buildClientConfig(
|
||||
connection: HostConnection,
|
||||
serverId?: string
|
||||
): Promise<DaemonClientConfig> {
|
||||
@@ -96,7 +96,7 @@ async function buildClientConfig(
|
||||
};
|
||||
}
|
||||
|
||||
function connectAndProbe(
|
||||
export function connectAndProbe(
|
||||
config: DaemonClientConfig,
|
||||
timeoutMs: number,
|
||||
): Promise<{ client: DaemonClient; serverId: string; hostname: string | null }> {
|
||||
@@ -152,26 +152,10 @@ function resolveTimeout(connection: HostConnection, options?: ProbeOptions): num
|
||||
return connection.type === "relay" ? 10_000 : 6_000;
|
||||
}
|
||||
|
||||
export async function probeConnection(
|
||||
export async function connectToDaemon(
|
||||
connection: HostConnection,
|
||||
options?: ProbeOptions,
|
||||
): Promise<{ serverId: string; hostname: string | null }> {
|
||||
): Promise<{ client: DaemonClient; serverId: string; hostname: string | null }> {
|
||||
const config = await buildClientConfig(connection, options?.serverId);
|
||||
const { client, serverId, hostname } = await connectAndProbe(config, resolveTimeout(connection, options));
|
||||
await client.close().catch(() => undefined);
|
||||
return { serverId, hostname };
|
||||
}
|
||||
|
||||
export async function measureConnectionLatency(
|
||||
connection: HostConnection,
|
||||
options?: ProbeOptions,
|
||||
): Promise<number> {
|
||||
const config = await buildClientConfig(connection, options?.serverId);
|
||||
const { client } = await connectAndProbe(config, resolveTimeout(connection, options));
|
||||
try {
|
||||
const { rttMs } = await client.ping({ timeoutMs: 5000 });
|
||||
return rttMs;
|
||||
} finally {
|
||||
await client.close().catch(() => undefined);
|
||||
}
|
||||
return connectAndProbe(config, resolveTimeout(connection, options));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user