import { err, ok, type Result } from "../../domain/result.js"; /** Retain a count, first failure and interruption fact with their observations. */ export interface SamplingDiagnostics { readonly count: number; readonly first: string | null; readonly interrupted: boolean; } export interface SamplingObservation { readonly value: T; readonly diagnostics: SamplingDiagnostics; } export type SamplingReadFailure = | { readonly kind: "cancelled"; readonly reason: unknown } | { readonly kind: "unavailable"; readonly systemCode: string | undefined; readonly diagnostic: string; }; export const mergeSamplingDiagnostics = ( ...parts: readonly SamplingDiagnostics[] ): SamplingDiagnostics => ({ count: parts.reduce((count, part) => count + part.count, 0), first: parts.find((part) => part.first !== null)?.first ?? null, interrupted: parts.some((part) => part.interrupted), }); export const samplingObservation = ( value: T, ...diagnostics: readonly SamplingDiagnostics[] ): SamplingObservation => ({ value, diagnostics: mergeSamplingDiagnostics(...diagnostics), }); export const samplingFailure = (diagnostic: string): SamplingDiagnostics => ({ count: 1, first: diagnostic, interrupted: false, }); /** An interrupted attempt left an observation or declared traversal unfinished. */ export const samplingInterrupted = (): SamplingDiagnostics => ({ count: 0, first: null, interrupted: true, }); /** Only this attempt's abort can end a read without a failure observation. */ export const isSamplingAbort = (cause: unknown, signal: AbortSignal): boolean => signal.aborted && (cause === signal.reason || (cause instanceof Error && cause.name === "AbortError" && cause.cause === signal.reason)); /** Settle each issued read, including peers still completing after shutdown. */ export const readSamplingSource = async ( source: string, signal: AbortSignal, read: () => Promise, ): Promise> => { if (signal.aborted) return err({ kind: "cancelled", reason: signal.reason }); try { return ok(await read()); } catch (cause: unknown) { if (isSamplingAbort(cause, signal)) return err({ kind: "cancelled", reason: signal.reason }); const systemCode = cause instanceof Error && "code" in cause && typeof cause.code === "string" ? cause.code : undefined; const reason = cause instanceof Error ? `${cause.name}: ${cause.message}` : String(cause); return err({ kind: "unavailable", systemCode, diagnostic: `${source}: ${systemCode === undefined ? "" : `${systemCode}: `}${reason}`, }); } }; export const samplingReadObservation = ( result: Result, ): SamplingObservation => result.ok ? samplingObservation(result.value) : samplingObservation( undefined, result.error.kind === "cancelled" ? samplingInterrupted() : samplingFailure(result.error.diagnostic), ); /** Missing procfs entries are expected exit races; denied reads stay unknown. */ export const readProcSamplingSource = async ( path: string, signal: AbortSignal, read: () => Promise, ): Promise> => { const result = await readSamplingSource(path, signal, read); if ( !result.ok && result.error.kind === "unavailable" && (result.error.systemCode === "ENOENT" || result.error.systemCode === "ESRCH") ) return samplingObservation(undefined); return samplingReadObservation(result); };