mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 17:59:08 +00:00
fix(kuna): mark project-dependent operations unavailable on export failure (#8748)
* fix(kuna): mark project-dependent operations unavailable on export failure * fix(providers): preserve sibling operations in capability error copies * fix(kuna): propagate sibling unavailability on export fallback * fix(binary): preserve observed sibling recovery instructions across fallback observations * fix(binary): build sibling unavailability from structured reasons without rewriting display text * test(kuna): synchronize fallback test on settled export workspace retirement * test(kuna): release and join export synchronization barrier across exit paths * test(kuna): synchronize fallback test on observed export process exit * test(kuna): gate fallback completion on settled export cache build * test(kuna): preserve build promise chain and restore spy after teardown
This commit is contained in:
1 parent
996977edf2
commit
9044b6fb36
10 files changed
+498
-18
No files matched your search
@@ -1,4 +1,5 @@
|
||||
import type { AnalysisError } from "../../domain/analysisErrorBase.js";
|
||||
import { AnalysisCapabilityUnavailableError } from "../../domain/analysisErrorCore.js";
|
||||
import type { Result } from "../../domain/result.js";
|
||||
import type { CapabilityDescriptor } from "../AnalysisProvider.js";
|
||||
|
||||
@@ -96,12 +97,37 @@ export class SessionRuntimeAvailability {
|
||||
if (result.ok) {
|
||||
operation.succeeded = Math.max(operation.succeeded, dispatch);
|
||||
provider.succeeded = Math.max(provider.succeeded, dispatch);
|
||||
// A success can only remove unavailability.
|
||||
if (this.#projected.size === 0) return false;
|
||||
const siblingUnavailability =
|
||||
typeof result.value === "object" &&
|
||||
result.value !== null &&
|
||||
"siblingUnavailability" in result.value &&
|
||||
result.value.siblingUnavailability instanceof
|
||||
AnalysisCapabilityUnavailableError
|
||||
? result.value.siblingUnavailability
|
||||
: undefined;
|
||||
if (siblingUnavailability !== undefined) {
|
||||
this.#observeSiblingUnavailability(
|
||||
dispatch,
|
||||
capability.operation,
|
||||
siblingUnavailability,
|
||||
);
|
||||
} else if (this.#projected.size === 0) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
const reason = runtimeFailureReason(result.error);
|
||||
if (reason === undefined) return false;
|
||||
operation.failure = newer(operation.failure, { dispatch, reason });
|
||||
if (
|
||||
result.error instanceof AnalysisCapabilityUnavailableError &&
|
||||
result.error.siblingOperations !== undefined
|
||||
) {
|
||||
this.#observeSiblingUnavailability(
|
||||
dispatch,
|
||||
capability.operation,
|
||||
result.error,
|
||||
);
|
||||
}
|
||||
if (PROVIDER_WIDE_FAILURES.has(result.error._tag))
|
||||
provider.failure = newer(provider.failure, {
|
||||
dispatch,
|
||||
@@ -112,6 +138,34 @@ export class SessionRuntimeAvailability {
|
||||
return this.#project(route);
|
||||
}
|
||||
|
||||
#observeSiblingUnavailability(
|
||||
dispatch: number,
|
||||
currentOperation: string,
|
||||
error: AnalysisCapabilityUnavailableError,
|
||||
): void {
|
||||
if (error.siblingOperations === undefined) return;
|
||||
for (const sibling of error.siblingOperations) {
|
||||
if (sibling !== currentOperation) {
|
||||
const siblingOutcomes = outcomes(this.#operations, sibling);
|
||||
const activeFailure =
|
||||
siblingOutcomes.failure !== undefined &&
|
||||
siblingOutcomes.failure.dispatch > siblingOutcomes.succeeded
|
||||
? siblingOutcomes.failure
|
||||
: undefined;
|
||||
const reason =
|
||||
activeFailure?.reason ??
|
||||
error.siblingReasons?.[sibling] ??
|
||||
(error.remediationAction !== undefined
|
||||
? `Provider ${error.providerId} cannot execute ${sibling}: ${error.reason}. ${error.remediationAction}`
|
||||
: `Provider ${error.providerId} cannot execute ${sibling}: ${error.reason}`);
|
||||
siblingOutcomes.failure = newer(siblingOutcomes.failure, {
|
||||
dispatch,
|
||||
reason,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Forget runtime outcomes when the active provider client is replaced. */
|
||||
clear(): boolean {
|
||||
this.#operations.clear();
|
||||
|
||||
Reference in new issue
Block a user