Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions packages/smooth-api-ts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,17 @@ export function createSmoothFetch<T>(globalConfig: SmoothFetchConfig<T>) {
const retryOn = globalConfig.retryOn ?? DEFAULT_RETRY_ON;
const breaker = new CircuitBreakerState(
globalConfig.circuitBreaker,
globalConfig.onCircuitStateChange
? (event) => safeInvoke(globalConfig.onCircuitStateChange, event)
: undefined
(event) => {
if (globalConfig.onCircuitStateChange) {
safeInvoke(globalConfig.onCircuitStateChange, event);
}
if (event.to === 'OPEN' && globalConfig.onCircuitOpen) {
safeInvoke(globalConfig.onCircuitOpen, {
domain: event.domain,
failureCount: event.failureCount,
});
}
}
);
const deduplicator = globalConfig.deduplication
? new RequestDeduplicator(globalConfig.deduplication.keyFn)
Expand Down
19 changes: 14 additions & 5 deletions packages/smooth-api-ts/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ export interface CircuitStateChangeEvent {
failureCount: number;
}

export interface CircuitOpenEvent {
domain: string;
failureCount: number;
}

/**
* Custom predicate function to determine if an attempt should be retried.
* Receives either (response, undefined) on HTTP completion or (undefined, error) on network/catch errors.
Expand Down Expand Up @@ -88,8 +93,16 @@ export interface FailureContext {
export type RequestSuccessContext = SuccessContext;
export type RequestFailureContext = FailureContext;

export interface MetricsHooks {
onRetry?: (context: RetryContext) => void | Promise<void>;
onFailure?: (context: FailureContext) => void | Promise<void>;
onSuccess?: (context: SuccessContext) => void | Promise<void>;
onCircuitOpen?: (event: CircuitOpenEvent) => void | Promise<void>;
onCircuitStateChange?: (event: CircuitStateChangeEvent) => void | Promise<void>;
}

// T types the fallback payload so callers get inference at the use site.
export interface SmoothFetchConfig<T = unknown> {
export interface SmoothFetchConfig<T = unknown> extends MetricsHooks {
backoff?: Partial<BackoffConfig>;
circuitBreaker?: Partial<CircuitBreakerConfig>;
fallback?: T; // returned immediately on an OPEN circuit, no network IO
Expand All @@ -113,10 +126,6 @@ export interface SmoothFetchConfig<T = unknown> {
* Must be a positive finite number.
*/
timeoutMs?: number;
onRetry?: (context: RetryContext) => void | Promise<void>;
onCircuitStateChange?: (event: CircuitStateChangeEvent) => void | Promise<void>;
onSuccess?: (context: SuccessContext) => void | Promise<void>;
onFailure?: (context: FailureContext) => void | Promise<void>;
}

/** @deprecated use SmoothFetchConfig instead */
Expand Down
Loading