@gravito/core 1.6.1 → 2.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/README.md +100 -6
- package/README.zh-TW.md +101 -6
- package/dist/Application.d.ts +256 -0
- package/dist/CommandKernel.d.ts +33 -0
- package/dist/ConfigManager.d.ts +65 -0
- package/dist/Container/RequestScopeManager.d.ts +62 -0
- package/dist/Container/RequestScopeMetrics.d.ts +144 -0
- package/dist/Container.d.ts +153 -0
- package/dist/ErrorHandler.d.ts +66 -0
- package/dist/Event.d.ts +5 -0
- package/dist/EventManager.d.ts +123 -0
- package/dist/GlobalErrorHandlers.d.ts +47 -0
- package/dist/GravitoServer.d.ts +28 -0
- package/dist/HookManager.d.ts +435 -0
- package/dist/Listener.d.ts +4 -0
- package/dist/Logger.d.ts +20 -0
- package/dist/PlanetCore.d.ts +402 -0
- package/dist/RequestContext.d.ts +97 -0
- package/dist/Route.d.ts +36 -0
- package/dist/Router.d.ts +270 -0
- package/dist/ServiceProvider.d.ts +178 -0
- package/dist/adapters/GravitoEngineAdapter.d.ts +27 -0
- package/dist/adapters/bun/AdaptiveAdapter.d.ts +99 -0
- package/dist/adapters/bun/BunContext.d.ts +54 -0
- package/dist/adapters/bun/BunNativeAdapter.d.ts +66 -0
- package/dist/adapters/bun/BunRequest.d.ts +31 -0
- package/dist/adapters/bun/BunWebSocketHandler.d.ts +48 -0
- package/dist/adapters/bun/RadixNode.d.ts +19 -0
- package/dist/adapters/bun/RadixRouter.d.ts +32 -0
- package/dist/adapters/bun/index.d.ts +7 -0
- package/dist/adapters/bun/types.d.ts +20 -0
- package/dist/adapters/index.d.ts +12 -0
- package/dist/adapters/types.d.ts +235 -0
- package/dist/binary/BinaryUtils.d.ts +105 -0
- package/dist/binary/index.d.ts +5 -0
- package/dist/cli/queue-commands.d.ts +6 -0
- package/dist/compat/async-local-storage.browser.d.ts +9 -0
- package/dist/compat/async-local-storage.d.ts +7 -0
- package/dist/compat/crypto.browser.d.ts +5 -0
- package/dist/compat/crypto.d.ts +6 -0
- package/dist/compat.cjs +42 -11
- package/dist/compat.cjs.map +9 -0
- package/dist/compat.d.ts +23 -1
- package/dist/compat.js +3 -0
- package/dist/compat.js.map +9 -0
- package/dist/engine/AOTRouter.d.ts +139 -0
- package/dist/engine/FastContext.d.ts +141 -0
- package/dist/engine/Gravito.d.ts +131 -0
- package/dist/engine/MinimalContext.d.ts +102 -0
- package/dist/engine/analyzer.d.ts +113 -0
- package/dist/engine/constants.d.ts +23 -0
- package/dist/engine/index.cjs +576 -647
- package/dist/engine/index.cjs.map +22 -0
- package/dist/engine/index.d.ts +14 -910
- package/dist/engine/index.js +576 -623
- package/dist/engine/index.js.map +22 -0
- package/dist/engine/path.d.ts +26 -0
- package/dist/engine/pool.d.ts +83 -0
- package/dist/engine/types.d.ts +149 -0
- package/dist/error-handling/RequestScopeErrorContext.d.ts +126 -0
- package/dist/events/BackpressureManager.d.ts +215 -0
- package/dist/events/CircuitBreaker.d.ts +229 -0
- package/dist/events/DeadLetterQueue.d.ts +219 -0
- package/dist/events/EventBackend.d.ts +12 -0
- package/dist/events/EventOptions.d.ts +204 -0
- package/dist/events/EventPriorityQueue.d.ts +63 -0
- package/dist/events/FlowControlStrategy.d.ts +109 -0
- package/dist/events/IdempotencyCache.d.ts +60 -0
- package/dist/events/MessageQueueBridge.d.ts +184 -0
- package/dist/events/PriorityEscalationManager.d.ts +82 -0
- package/dist/events/RetryScheduler.d.ts +104 -0
- package/dist/events/WorkerPool.d.ts +98 -0
- package/dist/events/WorkerPoolConfig.d.ts +153 -0
- package/dist/events/WorkerPoolMetrics.d.ts +65 -0
- package/dist/events/aggregation/AggregationWindow.d.ts +77 -0
- package/dist/events/aggregation/DeduplicationManager.d.ts +135 -0
- package/dist/events/aggregation/EventAggregationManager.d.ts +108 -0
- package/dist/events/aggregation/EventBatcher.d.ts +99 -0
- package/dist/events/aggregation/index.d.ts +10 -0
- package/dist/events/aggregation/types.d.ts +117 -0
- package/dist/events/index.d.ts +26 -0
- package/dist/events/observability/EventMetrics.d.ts +132 -0
- package/dist/events/observability/EventTracer.d.ts +68 -0
- package/dist/events/observability/EventTracing.d.ts +161 -0
- package/dist/events/observability/OTelEventMetrics.d.ts +332 -0
- package/dist/events/observability/ObservableHookManager.d.ts +108 -0
- package/dist/events/observability/StreamWorkerMetrics.d.ts +76 -0
- package/dist/events/observability/index.d.ts +24 -0
- package/dist/events/observability/metrics-types.d.ts +16 -0
- package/dist/events/queue-core.d.ts +77 -0
- package/dist/events/task-executor.d.ts +51 -0
- package/dist/events/types.d.ts +134 -0
- package/dist/exceptions/AuthenticationException.d.ts +8 -0
- package/dist/exceptions/AuthorizationException.d.ts +8 -0
- package/dist/exceptions/CircularDependencyException.d.ts +9 -0
- package/dist/exceptions/GravitoException.d.ts +23 -0
- package/dist/exceptions/HttpException.d.ts +9 -0
- package/dist/exceptions/ModelNotFoundException.d.ts +10 -0
- package/dist/exceptions/ValidationException.d.ts +22 -0
- package/dist/exceptions/index.d.ts +7 -0
- package/dist/ffi/NativeAccelerator.d.ts +69 -0
- package/dist/ffi/NativeHasher.d.ts +139 -0
- package/dist/ffi/cbor-fallback.d.ts +96 -0
- package/dist/ffi/hash-fallback.d.ts +33 -0
- package/dist/ffi/index.cjs +621 -0
- package/dist/ffi/index.cjs.map +14 -0
- package/dist/ffi/index.d.ts +10 -0
- package/dist/ffi/index.js +602 -0
- package/dist/ffi/index.js.map +14 -0
- package/dist/ffi/types.d.ts +135 -0
- package/dist/health/HealthProvider.d.ts +67 -0
- package/dist/helpers/Arr.d.ts +19 -0
- package/dist/helpers/Str.d.ts +38 -0
- package/dist/helpers/data.d.ts +25 -0
- package/dist/helpers/errors.d.ts +34 -0
- package/dist/helpers/response.d.ts +41 -0
- package/dist/helpers.d.ts +338 -0
- package/dist/hooks/ActionManager.d.ts +132 -0
- package/dist/hooks/AsyncDetector.d.ts +84 -0
- package/dist/hooks/FilterManager.d.ts +71 -0
- package/dist/hooks/MigrationWarner.d.ts +24 -0
- package/dist/hooks/dlq-operations.d.ts +60 -0
- package/dist/hooks/index.d.ts +11 -0
- package/dist/hooks/types.d.ts +107 -0
- package/dist/http/CookieJar.d.ts +51 -0
- package/dist/http/cookie.d.ts +29 -0
- package/dist/http/index.d.ts +12 -0
- package/dist/{compat-CI8hiulX.d.cts → http/types.d.ts} +29 -16
- package/dist/index.browser.d.ts +34 -0
- package/dist/index.cjs +10525 -11171
- package/dist/index.cjs.map +168 -0
- package/dist/index.d.ts +58 -10981
- package/dist/index.js +10861 -10997
- package/dist/index.js.map +168 -0
- package/dist/observability/QueueDashboard.d.ts +136 -0
- package/dist/observability/contracts.d.ts +137 -0
- package/dist/observability/index.d.ts +13 -0
- package/dist/reliability/DeadLetterQueueManager.d.ts +349 -0
- package/dist/reliability/RetryPolicy.d.ts +217 -0
- package/dist/reliability/index.d.ts +6 -0
- package/dist/router/ControllerDispatcher.d.ts +12 -0
- package/dist/router/RequestValidator.d.ts +20 -0
- package/dist/runtime/adapter-bun.d.ts +12 -0
- package/dist/runtime/adapter-deno.d.ts +12 -0
- package/dist/runtime/adapter-node.d.ts +12 -0
- package/dist/runtime/adapter-unknown.d.ts +13 -0
- package/dist/runtime/archive.d.ts +17 -0
- package/dist/runtime/compression.d.ts +21 -0
- package/dist/runtime/deep-equals.d.ts +56 -0
- package/dist/runtime/detection.d.ts +22 -0
- package/dist/runtime/escape.d.ts +34 -0
- package/dist/runtime/index.browser.d.ts +20 -0
- package/dist/runtime/index.d.ts +44 -0
- package/dist/runtime/markdown.d.ts +44 -0
- package/dist/runtime/types.d.ts +436 -0
- package/dist/runtime-helpers.d.ts +67 -0
- package/dist/runtime.d.ts +11 -0
- package/dist/security/Encrypter.d.ts +33 -0
- package/dist/security/Hasher.d.ts +29 -0
- package/dist/testing/HttpTester.d.ts +39 -0
- package/dist/testing/TestResponse.d.ts +78 -0
- package/dist/testing/index.d.ts +2 -0
- package/dist/transpiler-utils.d.ts +170 -0
- package/dist/types/events.d.ts +94 -0
- package/dist/types.d.ts +13 -0
- package/package.json +21 -52
- package/src/ffi/native/cbor.c +1148 -0
- package/dist/Metrics-VOWWRNNR.js +0 -219
- package/dist/chunk-R5U7XKVJ.js +0 -16
- package/dist/compat-CI8hiulX.d.ts +0 -376
- package/dist/compat.d.cts +0 -1
- package/dist/engine/index.d.cts +0 -922
- package/dist/index.d.cts +0 -11008
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import type { DeadLetterQueue } from '../events/DeadLetterQueue';
|
|
2
|
+
import type { EventPriorityQueue } from '../events/EventPriorityQueue';
|
|
3
|
+
import type { MessageQueueBridge } from '../events/MessageQueueBridge';
|
|
4
|
+
import type { WorkerPool } from '../events/WorkerPool';
|
|
5
|
+
import type { HookManager } from '../HookManager';
|
|
6
|
+
/**
|
|
7
|
+
* Configuration for QueueDashboard
|
|
8
|
+
* All subsystem references are optional to support progressive integration
|
|
9
|
+
*/
|
|
10
|
+
export interface QueueDashboardConfig {
|
|
11
|
+
eventQueue?: EventPriorityQueue;
|
|
12
|
+
workerPool?: WorkerPool;
|
|
13
|
+
hookManager?: HookManager;
|
|
14
|
+
dlq?: DeadLetterQueue;
|
|
15
|
+
messageQueueBridge?: MessageQueueBridge;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Queue depth and backpressure metrics
|
|
19
|
+
*/
|
|
20
|
+
export interface QueueMetrics {
|
|
21
|
+
depth: {
|
|
22
|
+
total: number;
|
|
23
|
+
high: number;
|
|
24
|
+
normal: number;
|
|
25
|
+
low: number;
|
|
26
|
+
};
|
|
27
|
+
backpressure: {
|
|
28
|
+
state: string;
|
|
29
|
+
rejectedCount: number;
|
|
30
|
+
degradedCount: number;
|
|
31
|
+
enqueueRate: number;
|
|
32
|
+
};
|
|
33
|
+
processing: boolean;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Worker pool and thread statistics
|
|
37
|
+
*/
|
|
38
|
+
export interface WorkerMetrics {
|
|
39
|
+
poolSize: number;
|
|
40
|
+
activeWorkers: number;
|
|
41
|
+
utilization: number;
|
|
42
|
+
queueDepth: number;
|
|
43
|
+
totalProcessed: number;
|
|
44
|
+
totalSuccess: number;
|
|
45
|
+
totalFailures: number;
|
|
46
|
+
successRate: number;
|
|
47
|
+
workers: Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
state: string;
|
|
50
|
+
tasksProcessed: number;
|
|
51
|
+
tasksSucceeded: number;
|
|
52
|
+
tasksFailed: number;
|
|
53
|
+
avgDurationMs: number;
|
|
54
|
+
currentLoad: number;
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Timeline event for job processing history
|
|
59
|
+
*/
|
|
60
|
+
export interface JobEvent {
|
|
61
|
+
id: string;
|
|
62
|
+
hook: string;
|
|
63
|
+
status: 'pending' | 'processing' | 'completed' | 'failed' | 'in_dlq';
|
|
64
|
+
priority: string;
|
|
65
|
+
createdAt: number;
|
|
66
|
+
error?: string;
|
|
67
|
+
retryCount: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Error statistics and circuit breaker status
|
|
71
|
+
*/
|
|
72
|
+
export interface ErrorStats {
|
|
73
|
+
totalErrors: number;
|
|
74
|
+
byEvent: Record<string, number>;
|
|
75
|
+
circuitBreakers: Array<{
|
|
76
|
+
eventName: string;
|
|
77
|
+
state: string;
|
|
78
|
+
failures: number;
|
|
79
|
+
successes: number;
|
|
80
|
+
}>;
|
|
81
|
+
dlqCount: number;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Complete dashboard snapshot at a point in time
|
|
85
|
+
*/
|
|
86
|
+
export interface DashboardSnapshot {
|
|
87
|
+
timestamp: number;
|
|
88
|
+
queue: QueueMetrics;
|
|
89
|
+
workers: WorkerMetrics;
|
|
90
|
+
timeline: JobEvent[];
|
|
91
|
+
errors: ErrorStats;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* QueueDashboard aggregates metrics from all event processing subsystems
|
|
95
|
+
* Uses Facade pattern to read-only aggregate data without modifying subsystems
|
|
96
|
+
*/
|
|
97
|
+
export declare class QueueDashboard {
|
|
98
|
+
private readonly config;
|
|
99
|
+
constructor(config: QueueDashboardConfig);
|
|
100
|
+
/**
|
|
101
|
+
* Get current queue metrics (depth, backpressure state, enqueue rate)
|
|
102
|
+
*/
|
|
103
|
+
getQueueMetrics(): QueueMetrics;
|
|
104
|
+
/**
|
|
105
|
+
* Get current worker pool metrics (size, utilization, success rate)
|
|
106
|
+
*/
|
|
107
|
+
getWorkerMetrics(): WorkerMetrics;
|
|
108
|
+
/**
|
|
109
|
+
* Get job event timeline from DLQ entries (recent failures)
|
|
110
|
+
* @param limit Maximum number of entries to return (default: 50)
|
|
111
|
+
*/
|
|
112
|
+
getJobTimeline(limit?: number): JobEvent[];
|
|
113
|
+
/**
|
|
114
|
+
* Get error statistics including circuit breaker status and DLQ counts
|
|
115
|
+
*/
|
|
116
|
+
getErrorBreakdown(): ErrorStats;
|
|
117
|
+
/**
|
|
118
|
+
* Export metrics in JSON or Prometheus format
|
|
119
|
+
* @param format Export format: 'json' or 'prometheus'
|
|
120
|
+
*/
|
|
121
|
+
exportMetrics(format: 'json' | 'prometheus'): string;
|
|
122
|
+
/**
|
|
123
|
+
* Get complete snapshot of all metrics at a point in time
|
|
124
|
+
*/
|
|
125
|
+
getSnapshot(options?: {
|
|
126
|
+
timelineLimit?: number;
|
|
127
|
+
}): DashboardSnapshot;
|
|
128
|
+
/**
|
|
129
|
+
* Format metrics in Prometheus/OpenMetrics text format
|
|
130
|
+
*/
|
|
131
|
+
private formatPrometheus;
|
|
132
|
+
/**
|
|
133
|
+
* Escape special characters in Prometheus labels
|
|
134
|
+
*/
|
|
135
|
+
private escapePrometheusLabel;
|
|
136
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gravito/core - Observability Contracts
|
|
3
|
+
*
|
|
4
|
+
* Abstract interfaces for observability providers, decoupling core from OpenTelemetry.
|
|
5
|
+
* This allows @gravito/monitor to provide complete OTel implementations while core
|
|
6
|
+
* remains dependency-free.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Represents a tracing span for distributed tracing.
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export interface TracingSpan {
|
|
13
|
+
/**
|
|
14
|
+
* Add an event to the span.
|
|
15
|
+
*
|
|
16
|
+
* @param name - Event name
|
|
17
|
+
* @param attributes - Optional event attributes
|
|
18
|
+
*/
|
|
19
|
+
addEvent(name: string, attributes?: Record<string, string | number>): void;
|
|
20
|
+
/**
|
|
21
|
+
* Set the span status.
|
|
22
|
+
*
|
|
23
|
+
* @param code - Status code: 'OK' or 'ERROR'
|
|
24
|
+
* @param message - Optional error message
|
|
25
|
+
*/
|
|
26
|
+
setStatus(code: 'OK' | 'ERROR', message?: string): void;
|
|
27
|
+
/**
|
|
28
|
+
* End the span.
|
|
29
|
+
*/
|
|
30
|
+
end(): void;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Event tracing provider for distributed tracing of events.
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export interface EventTracingProvider {
|
|
37
|
+
/**
|
|
38
|
+
* Start a new tracing span for an event.
|
|
39
|
+
*
|
|
40
|
+
* @param name - Span name
|
|
41
|
+
* @returns A TracingSpan instance
|
|
42
|
+
*/
|
|
43
|
+
startSpan(name: string): TracingSpan;
|
|
44
|
+
/**
|
|
45
|
+
* Record custom metrics for an event.
|
|
46
|
+
*
|
|
47
|
+
* @param eventName - Name of the event
|
|
48
|
+
* @param metrics - Metrics to record (e.g., duration, count)
|
|
49
|
+
*/
|
|
50
|
+
recordMetrics(eventName: string, metrics: Record<string, number>): void;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Event metrics recorder for monitoring event processing.
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export interface EventMetricsRecorder {
|
|
57
|
+
/**
|
|
58
|
+
* Record event processing completion.
|
|
59
|
+
*
|
|
60
|
+
* @param eventName - Name of the event
|
|
61
|
+
* @param duration - Processing duration in milliseconds
|
|
62
|
+
* @param success - Whether processing was successful
|
|
63
|
+
*/
|
|
64
|
+
recordEventProcessed(eventName: string, duration: number, success: boolean): void;
|
|
65
|
+
/**
|
|
66
|
+
* Record event publication.
|
|
67
|
+
*
|
|
68
|
+
* @param eventName - Name of the event
|
|
69
|
+
*/
|
|
70
|
+
recordEventPublished(eventName: string): void;
|
|
71
|
+
/**
|
|
72
|
+
* Record event processing error.
|
|
73
|
+
*
|
|
74
|
+
* @param eventName - Name of the event
|
|
75
|
+
* @param error - The error that occurred
|
|
76
|
+
*/
|
|
77
|
+
recordEventError(eventName: string, error: Error): void;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Worker metrics provider for monitoring worker pool operations.
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export interface WorkerMetricsProvider {
|
|
84
|
+
/**
|
|
85
|
+
* Record worker pool startup.
|
|
86
|
+
*
|
|
87
|
+
* @param poolId - ID of the worker pool
|
|
88
|
+
*/
|
|
89
|
+
recordWorkerStartup(poolId: string): void;
|
|
90
|
+
/**
|
|
91
|
+
* Record task execution in a worker pool.
|
|
92
|
+
*
|
|
93
|
+
* @param poolId - ID of the worker pool
|
|
94
|
+
* @param duration - Task duration in milliseconds
|
|
95
|
+
* @param success - Whether task execution was successful
|
|
96
|
+
*/
|
|
97
|
+
recordTaskExecution(poolId: string, duration: number, success: boolean): void;
|
|
98
|
+
/**
|
|
99
|
+
* Record worker pool error.
|
|
100
|
+
*
|
|
101
|
+
* @param poolId - ID of the worker pool
|
|
102
|
+
* @param error - The error that occurred
|
|
103
|
+
*/
|
|
104
|
+
recordWorkerError(poolId: string, error: Error): void;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Main observability provider interface combining all observability capabilities.
|
|
108
|
+
* @public
|
|
109
|
+
*/
|
|
110
|
+
export interface ObservabilityProvider {
|
|
111
|
+
/**
|
|
112
|
+
* Event tracing provider (optional).
|
|
113
|
+
*/
|
|
114
|
+
eventTracing?: EventTracingProvider;
|
|
115
|
+
/**
|
|
116
|
+
* Event metrics recorder (optional).
|
|
117
|
+
*/
|
|
118
|
+
eventMetrics?: EventMetricsRecorder;
|
|
119
|
+
/**
|
|
120
|
+
* Worker metrics provider (optional).
|
|
121
|
+
*/
|
|
122
|
+
workerMetrics?: WorkerMetricsProvider;
|
|
123
|
+
/**
|
|
124
|
+
* General tracing provider (optional).
|
|
125
|
+
*/
|
|
126
|
+
tracing?: {
|
|
127
|
+
startSpan(name: string): TracingSpan;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Create a no-op observability provider.
|
|
132
|
+
* Used by default when no observability implementation is provided.
|
|
133
|
+
*
|
|
134
|
+
* @returns An ObservabilityProvider with all no-op implementations
|
|
135
|
+
* @internal
|
|
136
|
+
*/
|
|
137
|
+
export declare function createNoOpObservabilityProvider(): ObservabilityProvider;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gravito/core - Observability Module
|
|
3
|
+
*
|
|
4
|
+
* 提供分佈式追蹤、指標收集與監控功能。
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
export type { EventMetrics } from '../events/observability/EventMetrics';
|
|
9
|
+
export type { EventTracer } from '../events/observability/EventTracer';
|
|
10
|
+
export { EventTracing, type EventTracingConfig, getEventTracing, } from '../events/observability/EventTracing';
|
|
11
|
+
export { type ObservabilityConfig, ObservableHookManager, } from '../events/observability/ObservableHookManager';
|
|
12
|
+
export { createNoOpObservabilityProvider, type EventMetricsRecorder, type EventTracingProvider, type ObservabilityProvider, type TracingSpan, type WorkerMetricsProvider, } from './contracts';
|
|
13
|
+
export { type DashboardSnapshot, type ErrorStats, type JobEvent, QueueDashboard, type QueueDashboardConfig, type QueueMetrics, type WorkerMetrics, } from './QueueDashboard';
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gravito/core - Dead Letter Queue Manager
|
|
3
|
+
*
|
|
4
|
+
* 管理失敗事件的持久化存儲
|
|
5
|
+
* 支持 CRUD、重新入隊、批量重試和統計功能
|
|
6
|
+
*/
|
|
7
|
+
import type { EventOptions } from '../events/EventOptions';
|
|
8
|
+
import type { RetryPolicy } from './RetryPolicy';
|
|
9
|
+
/**
|
|
10
|
+
* DLQ 事件的數據庫記錄
|
|
11
|
+
*/
|
|
12
|
+
export interface DLQRecord {
|
|
13
|
+
id: number;
|
|
14
|
+
dlq_id: string;
|
|
15
|
+
event_name: string;
|
|
16
|
+
event_payload: unknown;
|
|
17
|
+
event_options: unknown;
|
|
18
|
+
attempt_count: number;
|
|
19
|
+
max_retries: number;
|
|
20
|
+
next_retry_at: string | null;
|
|
21
|
+
last_error: unknown;
|
|
22
|
+
status: 'pending' | 'requeued' | 'resolved' | 'abandoned';
|
|
23
|
+
resolution_notes: string | null;
|
|
24
|
+
failed_at: string;
|
|
25
|
+
created_at: string;
|
|
26
|
+
updated_at: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* DLQ 事件查詢過濾選項(for DeadLetterQueueManager)
|
|
30
|
+
*/
|
|
31
|
+
export interface DLQManagerFilter {
|
|
32
|
+
/** 按事件名稱篩選 */
|
|
33
|
+
eventName?: string;
|
|
34
|
+
/** 按狀態篩選 */
|
|
35
|
+
status?: 'pending' | 'requeued' | 'resolved' | 'abandoned';
|
|
36
|
+
/** 開始時間 */
|
|
37
|
+
from?: Date;
|
|
38
|
+
/** 結束時間 */
|
|
39
|
+
to?: Date;
|
|
40
|
+
/** 結果數量限制 */
|
|
41
|
+
limit?: number;
|
|
42
|
+
/** 分頁偏移 */
|
|
43
|
+
offset?: number;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* DLQ 統計信息
|
|
47
|
+
*/
|
|
48
|
+
export interface DLQStats {
|
|
49
|
+
/** 事件總數 */
|
|
50
|
+
total: number;
|
|
51
|
+
/** 按事件名稱的統計 */
|
|
52
|
+
byEvent: Record<string, number>;
|
|
53
|
+
/** 按狀態的統計 */
|
|
54
|
+
byStatus: Record<string, number>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Dead Letter Queue 管理器
|
|
58
|
+
*
|
|
59
|
+
* 負責管理失敗事件的持久化存儲,支持:
|
|
60
|
+
* - 自動將失敗事件移至 DLQ
|
|
61
|
+
* - 查詢和篩選 DLQ 事件
|
|
62
|
+
* - 重新入隊單個或批量事件
|
|
63
|
+
* - 標記事件為已解決或已放棄
|
|
64
|
+
* - 查看統計信息
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```typescript
|
|
68
|
+
* const db = container.make('db') as any
|
|
69
|
+
* const dlqManager = new DeadLetterQueueManager(db)
|
|
70
|
+
*
|
|
71
|
+
* // 將失敗事件移至 DLQ
|
|
72
|
+
* const dlqId = await dlqManager.moveToDlq(
|
|
73
|
+
* 'order:created',
|
|
74
|
+
* { orderId: '123' },
|
|
75
|
+
* { retry: {...} },
|
|
76
|
+
* error,
|
|
77
|
+
* 3
|
|
78
|
+
* )
|
|
79
|
+
*
|
|
80
|
+
* // 查詢 DLQ 事件
|
|
81
|
+
* const events = await dlqManager.list({ event: 'order:created', status: 'pending' })
|
|
82
|
+
*
|
|
83
|
+
* // 重新入隊
|
|
84
|
+
* await dlqManager.requeue(dlqId)
|
|
85
|
+
*
|
|
86
|
+
* // 批量重試
|
|
87
|
+
* const result = await dlqManager.retryBatch({ eventName: 'order:created' })
|
|
88
|
+
*
|
|
89
|
+
* // 統計
|
|
90
|
+
* const stats = await dlqManager.getStats()
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export declare class DeadLetterQueueManager {
|
|
94
|
+
private db;
|
|
95
|
+
private retryEngine;
|
|
96
|
+
constructor(db: any);
|
|
97
|
+
/**
|
|
98
|
+
* 將失敗事件移至死信隊列
|
|
99
|
+
*
|
|
100
|
+
* @param eventName - 事件名稱
|
|
101
|
+
* @param payload - 事件負載
|
|
102
|
+
* @param options - 事件選項
|
|
103
|
+
* @param error - 導致失敗的錯誤
|
|
104
|
+
* @param attemptCount - 當前嘗試次數
|
|
105
|
+
* @param retryPolicy - 重試策略配置
|
|
106
|
+
* @returns DLQ 記錄的 UUID
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const dlqId = await dlqManager.moveToDlq(
|
|
111
|
+
* 'order:created',
|
|
112
|
+
* { orderId: 'ORD-123' },
|
|
113
|
+
* { retry: { maxRetries: 3, backoff: 'exponential' } },
|
|
114
|
+
* new Error('Service unavailable'),
|
|
115
|
+
* 3,
|
|
116
|
+
* { maxRetries: 3, backoff: 'exponential', initialDelayMs: 1000, maxDelayMs: 30000 }
|
|
117
|
+
* )
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
moveToDlq(eventName: string, payload: unknown, options: EventOptions, error: Error, attemptCount: number, retryPolicy?: RetryPolicy): Promise<string>;
|
|
121
|
+
/**
|
|
122
|
+
* 按 DLQ ID 獲取單個事件
|
|
123
|
+
*
|
|
124
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
125
|
+
* @returns DLQ 記錄,若不存在則返回 undefined
|
|
126
|
+
*
|
|
127
|
+
* @example
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const event = await dlqManager.getById('550e8400-e29b-41d4-a716-446655440000')
|
|
130
|
+
* if (event) {
|
|
131
|
+
* console.log(event.event_name, event.status)
|
|
132
|
+
* }
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
getById(dlqId: string): Promise<DLQRecord | undefined>;
|
|
136
|
+
/**
|
|
137
|
+
* 查詢 DLQ 事件
|
|
138
|
+
*
|
|
139
|
+
* @param filter - 查詢過濾條件
|
|
140
|
+
* @returns DLQ 記錄列表(按失敗時間倒序)
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```typescript
|
|
144
|
+
* // 查詢特定事件的待處理事件
|
|
145
|
+
* const events = await dlqManager.list({
|
|
146
|
+
* eventName: 'order:created',
|
|
147
|
+
* status: 'pending',
|
|
148
|
+
* limit: 50
|
|
149
|
+
* })
|
|
150
|
+
*
|
|
151
|
+
* // 查詢時間範圍內的所有失敗事件
|
|
152
|
+
* const eventsInRange = await dlqManager.list({
|
|
153
|
+
* from: new Date('2026-02-01'),
|
|
154
|
+
* to: new Date('2026-02-03'),
|
|
155
|
+
* limit: 100
|
|
156
|
+
* })
|
|
157
|
+
* ```
|
|
158
|
+
*/
|
|
159
|
+
list(filter?: DLQManagerFilter): Promise<DLQRecord[]>;
|
|
160
|
+
/**
|
|
161
|
+
* 重新入隊單個 DLQ 事件
|
|
162
|
+
*
|
|
163
|
+
* 重新入隊不會自動派發事件,而是標記狀態為 'requeued'
|
|
164
|
+
* 實際的事件派發應由調用者負責處理
|
|
165
|
+
*
|
|
166
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
167
|
+
* @throws 如果事件不存在
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* ```typescript
|
|
171
|
+
* const event = await dlqManager.getById(dlqId)
|
|
172
|
+
* if (event) {
|
|
173
|
+
* // 由調用者決定如何派發事件
|
|
174
|
+
* await eventSystem.doActionAsync(
|
|
175
|
+
* event.event_name,
|
|
176
|
+
* event.event_payload,
|
|
177
|
+
* event.event_options
|
|
178
|
+
* )
|
|
179
|
+
*
|
|
180
|
+
* // 標記為已重新入隊
|
|
181
|
+
* await dlqManager.requeue(dlqId)
|
|
182
|
+
* }
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
requeue(dlqId: string): Promise<void>;
|
|
186
|
+
/**
|
|
187
|
+
* 批量重新入隊 DLQ 事件
|
|
188
|
+
*
|
|
189
|
+
* @param filter - 查詢過濾條件
|
|
190
|
+
* @returns 包含處理結果的統計對象
|
|
191
|
+
*
|
|
192
|
+
* @example
|
|
193
|
+
* ```typescript
|
|
194
|
+
* const result = await dlqManager.retryBatch({
|
|
195
|
+
* eventName: 'order:created',
|
|
196
|
+
* status: 'pending'
|
|
197
|
+
* })
|
|
198
|
+
*
|
|
199
|
+
* console.log(`Success: ${result.succeeded}, Failed: ${result.failed}`)
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
retryBatch(filter?: DLQManagerFilter): Promise<{
|
|
203
|
+
total: number;
|
|
204
|
+
succeeded: number;
|
|
205
|
+
failed: number;
|
|
206
|
+
}>;
|
|
207
|
+
/**
|
|
208
|
+
* 標記 DLQ 事件為已解決
|
|
209
|
+
*
|
|
210
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
211
|
+
* @param notes - 解決說明
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```typescript
|
|
215
|
+
* await dlqManager.resolve(dlqId, 'Manual fix applied: Database issue resolved')
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
resolve(dlqId: string, notes?: string): Promise<void>;
|
|
219
|
+
/**
|
|
220
|
+
* 放棄 DLQ 事件(不再重試)
|
|
221
|
+
*
|
|
222
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
223
|
+
* @param reason - 放棄原因
|
|
224
|
+
*
|
|
225
|
+
* @example
|
|
226
|
+
* ```typescript
|
|
227
|
+
* await dlqManager.abandon(dlqId, 'Data corrupted, cannot recover')
|
|
228
|
+
* ```
|
|
229
|
+
*/
|
|
230
|
+
abandon(dlqId: string, reason?: string): Promise<void>;
|
|
231
|
+
/**
|
|
232
|
+
* 更新 DLQ 事件狀態
|
|
233
|
+
*
|
|
234
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
235
|
+
* @param status - 新狀態
|
|
236
|
+
* @param notes - 狀態變更說明
|
|
237
|
+
* @throws 如果事件不存在
|
|
238
|
+
*
|
|
239
|
+
* @internal
|
|
240
|
+
*/
|
|
241
|
+
updateStatus(dlqId: string, status: 'pending' | 'requeued' | 'resolved' | 'abandoned', notes?: string): Promise<void>;
|
|
242
|
+
/**
|
|
243
|
+
* 刪除單個 DLQ 事件
|
|
244
|
+
*
|
|
245
|
+
* @param dlqId - DLQ 事件的 UUID
|
|
246
|
+
* @returns true 如果刪除成功,false 如果事件不存在
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* const deleted = await dlqManager.deleteEntry(dlqId)
|
|
251
|
+
* if (deleted) {
|
|
252
|
+
* console.log('Event deleted')
|
|
253
|
+
* }
|
|
254
|
+
* ```
|
|
255
|
+
*/
|
|
256
|
+
deleteEntry(dlqId: string): Promise<boolean>;
|
|
257
|
+
/**
|
|
258
|
+
* 刪除多個 DLQ 事件
|
|
259
|
+
*
|
|
260
|
+
* @param dlqIds - DLQ 事件 UUID 列表
|
|
261
|
+
* @returns 刪除的事件數量
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const deletedCount = await dlqManager.deleteEntries([id1, id2, id3])
|
|
266
|
+
* ```
|
|
267
|
+
*/
|
|
268
|
+
deleteEntries(dlqIds: string[]): Promise<number>;
|
|
269
|
+
/**
|
|
270
|
+
* 獲取 DLQ 統計信息
|
|
271
|
+
*
|
|
272
|
+
* @returns 包含總數、按事件名稱和狀態的統計信息
|
|
273
|
+
*
|
|
274
|
+
* @example
|
|
275
|
+
* ```typescript
|
|
276
|
+
* const stats = await dlqManager.getStats()
|
|
277
|
+
*
|
|
278
|
+
* console.log(`Total events: ${stats.total}`)
|
|
279
|
+
* console.log('By event:', stats.byEvent)
|
|
280
|
+
* // Output: { 'order:created': 145, 'payment:succeeded': 23 }
|
|
281
|
+
*
|
|
282
|
+
* console.log('By status:', stats.byStatus)
|
|
283
|
+
* // Output: { pending: 120, requeued: 15, resolved: 8, abandoned: 2 }
|
|
284
|
+
* ```
|
|
285
|
+
*/
|
|
286
|
+
getStats(): Promise<DLQStats>;
|
|
287
|
+
/**
|
|
288
|
+
* 獲取某個事件名稱的 DLQ 事件數
|
|
289
|
+
*
|
|
290
|
+
* @param eventName - 事件名稱
|
|
291
|
+
* @returns 事件數量
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* const count = await dlqManager.getCountByEvent('order:created')
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
getCountByEvent(eventName: string): Promise<number>;
|
|
299
|
+
/**
|
|
300
|
+
* 清空所有 DLQ 事件(慎用!)
|
|
301
|
+
*
|
|
302
|
+
* @param includeResolved - 是否包含已解決的事件
|
|
303
|
+
* @returns 清空的事件數量
|
|
304
|
+
*
|
|
305
|
+
* @example
|
|
306
|
+
* ```typescript
|
|
307
|
+
* // 只清空待處理的事件
|
|
308
|
+
* const count = await dlqManager.clear(false)
|
|
309
|
+
*
|
|
310
|
+
* // 清空所有事件(包括已解決和已放棄)
|
|
311
|
+
* const countAll = await dlqManager.clear(true)
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
clear(includeResolved?: boolean): Promise<number>;
|
|
315
|
+
/**
|
|
316
|
+
* 通過 Bull Job ID 查找 DLQ 記錄
|
|
317
|
+
*
|
|
318
|
+
* 用於 MessageQueueBridge 集成:當 Bull Queue job 失敗時,
|
|
319
|
+
* 通過 Job ID 查找相應的 DLQ 記錄。
|
|
320
|
+
*
|
|
321
|
+
* @param bullJobId - Bull Queue Job ID
|
|
322
|
+
* @returns DLQ 記錄或 undefined
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```typescript
|
|
326
|
+
* const record = await dlqManager.findByBullJobId('job-abc123')
|
|
327
|
+
* if (record) {
|
|
328
|
+
* console.log(`Event ${record.event_name} is in DLQ`)
|
|
329
|
+
* }
|
|
330
|
+
* ```
|
|
331
|
+
*/
|
|
332
|
+
findByBullJobId(bullJobId: string): Promise<DLQRecord | undefined>;
|
|
333
|
+
/**
|
|
334
|
+
* 調度延遲重試(整合 Bull Queue delayed jobs)
|
|
335
|
+
*
|
|
336
|
+
* 從 DLQ 中提取事件,通過 Bull Queue 的延遲 job 功能進行重試。
|
|
337
|
+
*
|
|
338
|
+
* @param dlqId - DLQ 記錄 ID
|
|
339
|
+
* @param delayMs - 延遲時間(毫秒)
|
|
340
|
+
* @throws 如果記錄不存在
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```typescript
|
|
344
|
+
* // 延遲 1 小時後重試
|
|
345
|
+
* await dlqManager.scheduleRetry('dlq-uuid-123', 3600000)
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
scheduleRetry(dlqId: string, delayMs: number): Promise<void>;
|
|
349
|
+
}
|