48 lines
1.8 KiB
TypeScript
48 lines
1.8 KiB
TypeScript
import type { StructuredJsonlLogger } from "./structured-log.js";
|
|
|
|
export class WorkerAiCallGate {
|
|
private readonly getStorageStatus: () => "active" | "full" | "unavailable";
|
|
private readonly logger: StructuredJsonlLogger;
|
|
|
|
constructor(input: {
|
|
getStorageStatus: () => "active" | "full" | "unavailable";
|
|
logger: StructuredJsonlLogger;
|
|
}) {
|
|
this.getStorageStatus = input.getStorageStatus;
|
|
this.logger = input.logger;
|
|
}
|
|
|
|
async execute<T>(correlationId: string, objectId: string, externalCall: () => Promise<T>) {
|
|
const initialStatus = this.getStorageStatus();
|
|
if (initialStatus === "full") return { reason: "storage_full" as const, status: "blocked" as const };
|
|
if (initialStatus === "unavailable") return { reason: "storage_unavailable" as const, status: "blocked" as const };
|
|
try {
|
|
this.logger.write({
|
|
correlation_id: correlationId,
|
|
error_category: "none",
|
|
object_id: objectId,
|
|
status_category: "starting",
|
|
});
|
|
} catch {
|
|
return { reason: "storage_unavailable" as const, status: "blocked" as const };
|
|
}
|
|
const statusAfterLog = this.getStorageStatus();
|
|
if (statusAfterLog === "full") return { reason: "storage_full" as const, status: "blocked" as const };
|
|
if (statusAfterLog === "unavailable") return { reason: "storage_unavailable" as const, status: "blocked" as const };
|
|
const started = Date.now();
|
|
const value = await externalCall();
|
|
try {
|
|
this.logger.write({
|
|
correlation_id: correlationId,
|
|
duration_ms: Date.now() - started,
|
|
error_category: "none",
|
|
object_id: objectId,
|
|
status_category: "completed",
|
|
});
|
|
} catch {
|
|
// The completed call cannot be undone; the write failure blocks every later call.
|
|
}
|
|
return { status: "completed" as const, value };
|
|
}
|
|
}
|