- Introduced ExecutionMode type for project execution modes (parallel, sequential). - Updated SetupOpts to use ExecutionMode instead of string literals. - Enhanced workflow states to include a new "In Review" state with appropriate transitions. - Implemented TestHarness for end-to-end testing, including command interception and workspace setup. - Created TestProvider for in-memory issue tracking during tests. - Refactored project registration and setup tools to utilize ExecutionMode. - Updated various tools to ensure compatibility with new workflow and execution modes. - Added new dependencies: cockatiel for resilience and zod for schema validation.
50 lines
1.3 KiB
TypeScript
50 lines
1.3 KiB
TypeScript
/**
|
|
* providers/resilience.ts — Retry and circuit breaker policies for provider calls.
|
|
*
|
|
* Uses cockatiel for lightweight resilience without heavyweight orchestration.
|
|
* Applied to GitHub/GitLab CLI calls that can fail due to network, rate limits, or timeouts.
|
|
*/
|
|
import {
|
|
ExponentialBackoff,
|
|
retry,
|
|
circuitBreaker,
|
|
ConsecutiveBreaker,
|
|
handleAll,
|
|
wrap,
|
|
type IPolicy,
|
|
} from "cockatiel";
|
|
|
|
/**
|
|
* Default retry policy: 3 attempts with exponential backoff.
|
|
* Handles all errors (network, timeout, CLI failure).
|
|
*/
|
|
const retryPolicy = retry(handleAll, {
|
|
maxAttempts: 3,
|
|
backoff: new ExponentialBackoff({
|
|
initialDelay: 500,
|
|
maxDelay: 5_000,
|
|
}),
|
|
});
|
|
|
|
/**
|
|
* Circuit breaker: opens after 5 consecutive failures, half-opens after 30s.
|
|
* Prevents hammering a provider that's down.
|
|
*/
|
|
const breakerPolicy = circuitBreaker(handleAll, {
|
|
halfOpenAfter: 30_000,
|
|
breaker: new ConsecutiveBreaker(5),
|
|
});
|
|
|
|
/**
|
|
* Combined policy: circuit breaker wrapping retry.
|
|
* If circuit is open, calls fail fast without retrying.
|
|
*/
|
|
export const providerPolicy: IPolicy = wrap(breakerPolicy, retryPolicy);
|
|
|
|
/**
|
|
* Execute a provider call with retry + circuit breaker.
|
|
*/
|
|
export function withResilience<T>(fn: () => Promise<T>): Promise<T> {
|
|
return providerPolicy.execute(() => fn());
|
|
}
|