Files
reverse-engineering-anything/src/providers/DeferredAnalysisClient.ts
T
morluto ff78165978 fix(kuna): own version-probe processes through output and cleanup
Use the shared command supervisor for installation probes and retain exact
process cleanup owners through doctor, profile resolution, and session health.
Preserve exit status, bounded captured output, cancellation reasons, and live
cleanup facts. Block subsequent inspection until retained cleanup is retried.

Generalize the existing inspection resource scope and migrate its consumers,
including verifier scripts; remove the verifier's duplicate raw version probe.

Validation: 116 distinct focused tests passed, including built CLI doctor with
inherited output, cancellation/finalization, cleanup retry, and fake-provider
verifier workflows. Build, check:fast, and test discovery passed. No real Kuna
distribution or analysis target was executed.

Synthetic Darwin inspection timing: first-call median 707ms versus 5.79ms;
same-process repeat 37.9ms versus 3.08ms. First use includes ownership-helper
preparation. Family CPU and actual peak family memory remain unmeasured.

Fixes #5557
2026-10-21 00:09:34 +08:00

85 lines
2.7 KiB
TypeScript

import type {
AnalysisClient,
RetainedResourceScope,
ProviderRuntimeLineageSnapshot,
ProviderRequestActivitySnapshot,
} from "../application/AnalysisProvider.js";
import type { ProviderOperationHealth } from "../domain/providerOperationHealth.js";
import { AnalysisError } from "../domain/analysisErrorBase.js";
import { ProviderAdapterError } from "../domain/providerAdapterError.js";
import { err } from "../domain/result.js";
import { AnalysisClientCreation } from "./AnalysisClientCreation.js";
/** Expose a closeable client before deferred prerequisite work starts. */
export class DeferredAnalysisClient implements AnalysisClient {
readonly #creation: AnalysisClientCreation;
readonly #providerId: string;
executeIfReady: NonNullable<AnalysisClient["executeIfReady"]> = (
operation,
parameters,
options,
) =>
this.#creation.readyClient?.executeIfReady?.(
operation,
parameters,
options,
) ?? Promise.resolve(undefined);
constructor(
loadClient: (
signal: AbortSignal,
resourceOwner: RetainedResourceScope,
) => Promise<AnalysisClient>,
providerId: string,
) {
this.#creation = new AnalysisClientCreation(providerId, loadClient);
this.#providerId = providerId;
}
execute: AnalysisClient["execute"] = async (
operation,
parameters,
options,
) => {
try {
const loaded = await this.#creation.acquire(operation, options?.signal);
if (!loaded.ok) return loaded;
if (this.#creation.readyClient !== loaded.value)
return err(
new ProviderAdapterError(this.#providerId, operation, {
diagnostics: { reason: "client_closed" },
}),
);
return await loaded.value.execute(operation, parameters, options);
} catch (cause: unknown) {
if (cause instanceof AnalysisError) return err(cause);
return err(
new ProviderAdapterError(this.#providerId, operation, {
cause,
}),
);
}
};
runtimeLineageSnapshots(): readonly ProviderRuntimeLineageSnapshot[] {
return this.#creation.ownedClient?.runtimeLineageSnapshots?.() ?? [];
}
requestActivitySnapshots(): readonly ProviderRequestActivitySnapshot[] {
return this.#creation.ownedClient?.requestActivitySnapshots?.() ?? [];
}
reuseReadiness(): "ready" | "blocked" | "unknown" {
if (!this.#creation.reusable || this.#creation.readyClient === undefined)
return "blocked";
return this.#creation.readyClient.reuseReadiness?.() ?? "unknown";
}
operationHealthSnapshot(): ProviderOperationHealth | undefined {
return this.#creation.ownedClient?.operationHealthSnapshot?.();
}
close: AnalysisClient["close"] = (options) => this.#creation.close(options);
}