@gravito/echo 3.1.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/errors/EchoError.d.ts +29 -0
- package/dist/errors/codes.d.ts +20 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/resilience/CircuitBreaker.d.ts +3 -114
- package/dist/resilience/index.d.ts +2 -1
- package/dist/types.d.ts +3 -1
- package/package.json +6 -3
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Echo error types
|
|
3
|
+
*
|
|
4
|
+
* @module @gravito/echo/errors
|
|
5
|
+
*/
|
|
6
|
+
import { InfrastructureException, type InfrastructureExceptionOptions } from '@gravito/core';
|
|
7
|
+
import type { EchoErrorCode } from './codes';
|
|
8
|
+
/**
|
|
9
|
+
* Base error class for Echo module.
|
|
10
|
+
*
|
|
11
|
+
* Provides structured error handling with error codes and messages.
|
|
12
|
+
* Extends InfrastructureException for unified error handling across Gravito.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* throw new EchoError('echo.unknown_provider', 'Unknown provider type: stripe')
|
|
17
|
+
* ```
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export declare class EchoError extends InfrastructureException {
|
|
21
|
+
/**
|
|
22
|
+
* Creates a new EchoError instance.
|
|
23
|
+
*
|
|
24
|
+
* @param code - The error code.
|
|
25
|
+
* @param message - The error message.
|
|
26
|
+
* @param options - Optional infrastructure exception options.
|
|
27
|
+
*/
|
|
28
|
+
constructor(code: EchoErrorCode, message: string, options?: InfrastructureExceptionOptions);
|
|
29
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Echo error codes
|
|
3
|
+
*
|
|
4
|
+
* Namespaced error codes for the Echo webhook module.
|
|
5
|
+
*
|
|
6
|
+
* @module @gravito/echo/errors
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Error codes for Echo module operations.
|
|
10
|
+
* Follows dot-separated namespace convention.
|
|
11
|
+
*/
|
|
12
|
+
export declare const EchoErrorCodes: {
|
|
13
|
+
readonly UNKNOWN_PROVIDER: "echo.unknown_provider";
|
|
14
|
+
readonly KEY_ROTATION_NOT_SET: "echo.key_rotation_not_set";
|
|
15
|
+
readonly NO_PRIMARY_KEY: "echo.no_primary_key";
|
|
16
|
+
readonly KEY_ROTATION_NOT_ENABLED: "echo.key_rotation_not_enabled";
|
|
17
|
+
readonly NO_DELIVERY_ATTEMPTS: "echo.no_delivery_attempts";
|
|
18
|
+
readonly INVALID_CONFIG: "echo.invalid_config";
|
|
19
|
+
};
|
|
20
|
+
export type EchoErrorCode = (typeof EchoErrorCodes)[keyof typeof EchoErrorCodes];
|
package/dist/index.d.ts
CHANGED
|
@@ -38,6 +38,9 @@
|
|
|
38
38
|
* @module @gravito/echo
|
|
39
39
|
*/
|
|
40
40
|
export type { DeadLetterEvent, DeadLetterQueue } from './dlq/DeadLetterQueue';
|
|
41
|
+
export { EchoError } from './errors/EchoError';
|
|
42
|
+
export { EchoErrorCodes } from './errors/codes';
|
|
43
|
+
export type { EchoErrorCode } from './errors/codes';
|
|
41
44
|
export { MemoryDeadLetterQueue } from './dlq/MemoryDeadLetterQueue';
|
|
42
45
|
export { createRequestBufferMiddleware, RequestBufferMiddleware } from './middleware';
|
|
43
46
|
export { OrbitEcho } from './OrbitEcho';
|
package/dist/index.js
CHANGED
|
@@ -26,9 +26,11 @@ export {
|
|
|
26
26
|
GitHubProvider,
|
|
27
27
|
GenericProvider,
|
|
28
28
|
EchoMetrics,
|
|
29
|
+
EchoErrorCodes,
|
|
30
|
+
EchoError,
|
|
29
31
|
ConsoleEchoLogger,
|
|
30
32
|
CircuitBreaker,
|
|
31
33
|
BaseProvider
|
|
32
34
|
};
|
|
33
35
|
|
|
34
|
-
//# debugId=
|
|
36
|
+
//# debugId=FCA02EA2A4A7000964756E2164756E21
|
package/dist/index.js.map
CHANGED
|
@@ -1,117 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* Protects downstream services from cascading failures by monitoring error rates
|
|
5
|
-
* and temporarily "tripping" the circuit when thresholds are exceeded. This
|
|
6
|
-
* prevents unnecessary load on struggling services and allows them time to recover.
|
|
7
|
-
*
|
|
2
|
+
* Circuit Breaker — re-exported from @gravito/resilience (canonical implementation).
|
|
3
|
+
* Per D-01: echo's duplicate CB is replaced with re-exports from @gravito/resilience.
|
|
8
4
|
* @module @gravito/echo/resilience
|
|
9
|
-
* @since 1.1.0
|
|
10
5
|
*/
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* State machine for managing downstream service availability via the Circuit Breaker pattern.
|
|
14
|
-
*
|
|
15
|
-
* This implementation tracks failures and successes to determine one of three states:
|
|
16
|
-
* - `CLOSED`: Healthy state. All requests are executed normally.
|
|
17
|
-
* - `OPEN`: Failing state. Trip thresholds exceeded; requests are rejected immediately to
|
|
18
|
-
* prevent cascading failure and give the target system time to recover.
|
|
19
|
-
* - `HALF_OPEN`: Recovery phase. Allows a limited number of test requests to determine
|
|
20
|
-
* if the downstream service has restored functionality.
|
|
21
|
-
*
|
|
22
|
-
* @example Protecting a fragile API call
|
|
23
|
-
* ```typescript
|
|
24
|
-
* const breaker = new CircuitBreaker('inventory-service', {
|
|
25
|
-
* failureThreshold: 5,
|
|
26
|
-
* openTimeout: 60000 // Stay open for 1 minute before testing recovery
|
|
27
|
-
* });
|
|
28
|
-
*
|
|
29
|
-
* try {
|
|
30
|
-
* const stock = await breaker.execute(async () => {
|
|
31
|
-
* return await apiClient.getInventory();
|
|
32
|
-
* });
|
|
33
|
-
* } catch (error) {
|
|
34
|
-
* if (error.message.includes('Circuit breaker is OPEN')) {
|
|
35
|
-
* // Redirect to fallback or return cached data
|
|
36
|
-
* }
|
|
37
|
-
* }
|
|
38
|
-
* ```
|
|
39
|
-
*
|
|
40
|
-
* @public
|
|
41
|
-
*/
|
|
42
|
-
export declare class CircuitBreaker {
|
|
43
|
-
private readonly name;
|
|
44
|
-
private state;
|
|
45
|
-
private failures;
|
|
46
|
-
private successes;
|
|
47
|
-
private lastFailureAt?;
|
|
48
|
-
private lastSuccessAt?;
|
|
49
|
-
private openedAt?;
|
|
50
|
-
private halfOpenAttempts;
|
|
51
|
-
private config;
|
|
52
|
-
/**
|
|
53
|
-
* Constructs a new CircuitBreaker for a specific resource, host, or service.
|
|
54
|
-
*
|
|
55
|
-
* @param name - A semantic identifier for the target being protected.
|
|
56
|
-
* @param config - Policy settings for failure thresholds, recovery timeouts, and callbacks.
|
|
57
|
-
*/
|
|
58
|
-
constructor(name: string, config?: CircuitBreakerConfig);
|
|
59
|
-
/**
|
|
60
|
-
* Executes an asynchronous operation within the safety window of the circuit breaker.
|
|
61
|
-
*
|
|
62
|
-
* This method will proactively check the circuit state. If the state is `OPEN`, it will
|
|
63
|
-
* throw an error immediately without invoking the provided function.
|
|
64
|
-
*
|
|
65
|
-
* @param fn - The asynchronous operation to be protected.
|
|
66
|
-
* @returns A promise resolving to the result of the protected operation.
|
|
67
|
-
* @throws {Error} If the circuit is currently `OPEN` or if the underlying operation fails.
|
|
68
|
-
*/
|
|
69
|
-
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
70
|
-
/**
|
|
71
|
-
* Records a successful operation and updates the state machine.
|
|
72
|
-
* In `HALF_OPEN` state, this contributes to the success threshold for closing the circuit.
|
|
73
|
-
*/
|
|
74
|
-
private onSuccess;
|
|
75
|
-
/**
|
|
76
|
-
* Records a failed operation and determines if the circuit should trip to `OPEN`.
|
|
77
|
-
* Any failure in `HALF_OPEN` state immediately trips the circuit back to `OPEN`.
|
|
78
|
-
*/
|
|
79
|
-
private onFailure;
|
|
80
|
-
/**
|
|
81
|
-
* Evaluates and performs automatic state transitions based on elapsed time and thresholds.
|
|
82
|
-
*/
|
|
83
|
-
private checkStateTransition;
|
|
84
|
-
/**
|
|
85
|
-
* Transitions the circuit to a new state and executes configured lifecycle callbacks.
|
|
86
|
-
*
|
|
87
|
-
* @param newState - The target state to transition into.
|
|
88
|
-
*/
|
|
89
|
-
private transitionTo;
|
|
90
|
-
/**
|
|
91
|
-
* Resets all internal counters and timers to their initial baseline state.
|
|
92
|
-
*/
|
|
93
|
-
private reset;
|
|
94
|
-
/**
|
|
95
|
-
* Retrieves a snapshot of the current health and performance metrics of the circuit.
|
|
96
|
-
*
|
|
97
|
-
* @returns An object containing state, failure counts, and activity timestamps.
|
|
98
|
-
*/
|
|
99
|
-
getMetrics(): CircuitBreakerMetrics;
|
|
100
|
-
/**
|
|
101
|
-
* Forcefully resets the circuit breaker to the `CLOSED` state.
|
|
102
|
-
* Useful for manual recovery scenarios after a service has been verified healthy.
|
|
103
|
-
*/
|
|
104
|
-
manualReset(): void;
|
|
105
|
-
/**
|
|
106
|
-
* Returns the current operational state of the circuit breaker.
|
|
107
|
-
*
|
|
108
|
-
* @returns The current state identifier.
|
|
109
|
-
*/
|
|
110
|
-
getState(): CircuitBreakerState;
|
|
111
|
-
/**
|
|
112
|
-
* Returns the semantic name assigned to this circuit breaker instance.
|
|
113
|
-
*
|
|
114
|
-
* @returns The name identifier.
|
|
115
|
-
*/
|
|
116
|
-
getName(): string;
|
|
117
|
-
}
|
|
6
|
+
export { CircuitBreaker, CircuitBreakerState, type CircuitBreakerOptions, type CircuitBreakerMetrics, type CircuitBreakerMetricsRecorder, } from '@gravito/resilience';
|
|
@@ -6,5 +6,6 @@
|
|
|
6
6
|
* @module @gravito/echo/resilience
|
|
7
7
|
* @since v1.1
|
|
8
8
|
*/
|
|
9
|
-
export type { CircuitBreakerConfig, CircuitBreakerMetrics
|
|
9
|
+
export type { CircuitBreakerConfig, CircuitBreakerMetrics } from '../types';
|
|
10
|
+
export { CircuitBreakerState } from '../types';
|
|
10
11
|
export { CircuitBreaker } from './CircuitBreaker';
|
package/dist/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CircuitBreakerState } from '@gravito/resilience';
|
|
1
2
|
import type { DeadLetterQueue } from './dlq/DeadLetterQueue';
|
|
2
3
|
import type { EchoLogger } from './observability/logging';
|
|
3
4
|
import type { MetricsProvider } from './observability/metrics';
|
|
@@ -235,6 +236,7 @@ export interface RequestBufferConfig {
|
|
|
235
236
|
}
|
|
236
237
|
/**
|
|
237
238
|
* The current operational state of a circuit breaker.
|
|
239
|
+
* Re-exported from @gravito/resilience (canonical source per D-01).
|
|
238
240
|
*
|
|
239
241
|
* - `CLOSED`: Healthy state, allowing all requests through.
|
|
240
242
|
* - `OPEN`: Failing state, blocking all requests to prevent cascading failure.
|
|
@@ -242,7 +244,7 @@ export interface RequestBufferConfig {
|
|
|
242
244
|
*
|
|
243
245
|
* @public
|
|
244
246
|
*/
|
|
245
|
-
export
|
|
247
|
+
export { CircuitBreakerState } from '@gravito/resilience';
|
|
246
248
|
/**
|
|
247
249
|
* Resilience configuration for outgoing webhook delivery.
|
|
248
250
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravito/echo",
|
|
3
3
|
"sideEffects": false,
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "4.0.0",
|
|
5
5
|
"description": "Enterprise-grade webhook handling for Gravito. Secure receiving and reliable sending.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.cjs",
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
"test:integration": "test $(find tests -name '*.integration.test.ts' 2>/dev/null | wc -l) -gt 0 && find tests -name '*.integration.test.ts' -print0 | xargs -0 bun test --timeout=10000 || echo 'No integration tests found'",
|
|
27
27
|
"typecheck": "bun tsc -p tsconfig.json --noEmit --skipLibCheck",
|
|
28
28
|
"test:coverage": "bun test --timeout=10000 --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run --bun scripts/check-coverage.ts",
|
|
29
|
-
"test:ci": "bun test --timeout=10000 --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run --bun scripts/check-coverage.ts"
|
|
29
|
+
"test:ci": "bun test --timeout=10000 --coverage --coverage-reporter=lcov --coverage-dir coverage && bun run --bun scripts/check-coverage.ts",
|
|
30
|
+
"publint": "publint"
|
|
30
31
|
},
|
|
31
32
|
"keywords": [
|
|
32
33
|
"gravito",
|
|
@@ -45,10 +46,12 @@
|
|
|
45
46
|
},
|
|
46
47
|
"homepage": "https://github.com/gravito-framework/gravito#readme",
|
|
47
48
|
"peerDependencies": {
|
|
48
|
-
"@gravito/core": "^
|
|
49
|
+
"@gravito/core": "^3.0.0",
|
|
50
|
+
"@gravito/resilience": "workspace:*"
|
|
49
51
|
},
|
|
50
52
|
"devDependencies": {
|
|
51
53
|
"@gravito/core": "workspace:*",
|
|
54
|
+
"@gravito/resilience": "workspace:*",
|
|
52
55
|
"bun-types": "latest",
|
|
53
56
|
"typescript": "^5.9.3"
|
|
54
57
|
},
|