@takentrade/takentrade-libs 2.0.8 → 3.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.
Files changed (44) hide show
  1. package/LICENSE +87 -0
  2. package/README.md +112 -743
  3. package/dist/common/health/health.controller.js +0 -2
  4. package/dist/common/index.d.ts +0 -2
  5. package/dist/common/index.js +0 -2
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +2 -0
  8. package/dist/metrics/circuit-breaker-metrics.service.d.ts +61 -0
  9. package/dist/metrics/circuit-breaker-metrics.service.js +149 -0
  10. package/dist/metrics/index.d.ts +5 -0
  11. package/dist/metrics/index.js +21 -0
  12. package/dist/metrics/metrics-registry.d.ts +50 -0
  13. package/dist/metrics/metrics-registry.js +156 -0
  14. package/dist/metrics/metrics-updater.d.ts +32 -0
  15. package/dist/metrics/metrics-updater.js +102 -0
  16. package/dist/metrics/metrics.controller.d.ts +11 -0
  17. package/dist/metrics/metrics.controller.js +32 -0
  18. package/dist/metrics/metrics.interface.d.ts +106 -0
  19. package/dist/metrics/metrics.interface.js +35 -0
  20. package/dist/metrics/metrics.module.d.ts +11 -0
  21. package/dist/metrics/metrics.module.js +39 -0
  22. package/dist/metrics/metrics.service.d.ts +50 -0
  23. package/dist/metrics/metrics.service.js +165 -0
  24. package/dist/resilience/circuit-breaker-event-handler.d.ts +16 -0
  25. package/dist/resilience/circuit-breaker-event-handler.js +70 -0
  26. package/dist/resilience/circuit-breaker-factory.d.ts +19 -0
  27. package/dist/resilience/circuit-breaker-factory.js +51 -0
  28. package/dist/resilience/circuit-breaker-stats.service.d.ts +37 -0
  29. package/dist/resilience/circuit-breaker-stats.service.js +69 -0
  30. package/dist/resilience/circuit-breaker.interface.d.ts +134 -0
  31. package/dist/resilience/circuit-breaker.interface.js +31 -0
  32. package/dist/{common/circuit-breaker → resilience}/circuit-breaker.module.js +1 -0
  33. package/dist/resilience/circuit-breaker.service.d.ts +119 -0
  34. package/dist/resilience/circuit-breaker.service.js +234 -0
  35. package/dist/resilience/index.d.ts +3 -0
  36. package/dist/resilience/index.js +19 -0
  37. package/dist/tsconfig.tsbuildinfo +1 -1
  38. package/dist/utils/dto/pagination.js +0 -6
  39. package/package.json +5 -2
  40. package/dist/common/circuit-breaker/circuit-breaker.service.d.ts +0 -13
  41. package/dist/common/circuit-breaker/circuit-breaker.service.js +0 -120
  42. package/dist/common/circuit-breaker/circuit-breaker.types.d.ts +0 -19
  43. package/dist/common/circuit-breaker/circuit-breaker.types.js +0 -9
  44. /package/dist/{common/circuit-breaker → resilience}/circuit-breaker.module.d.ts +0 -0
@@ -0,0 +1,106 @@
1
+ import { Counter, Gauge, Histogram, Summary, CounterConfiguration, GaugeConfiguration, HistogramConfiguration, SummaryConfiguration } from 'prom-client';
2
+ /**
3
+ * Metric types supported by the metrics service
4
+ */
5
+ export declare enum MetricType {
6
+ COUNTER = "counter",
7
+ GAUGE = "gauge",
8
+ HISTOGRAM = "histogram",
9
+ SUMMARY = "summary"
10
+ }
11
+ /**
12
+ * Configuration options for the metrics module
13
+ */
14
+ export interface MetricsModuleOptions {
15
+ /**
16
+ * Enable default metrics collection (CPU, memory, etc.)
17
+ * @default true
18
+ */
19
+ defaultMetrics?: boolean;
20
+ /**
21
+ * Prefix for all metric names
22
+ * @default ''
23
+ */
24
+ prefix?: string;
25
+ /**
26
+ * Default labels to add to all metrics
27
+ * @default {}
28
+ */
29
+ defaultLabels?: Record<string, string>;
30
+ /**
31
+ * Interval for collecting default metrics (in milliseconds)
32
+ * @default 10000
33
+ */
34
+ defaultMetricsInterval?: number;
35
+ /**
36
+ * Enable circuit breaker metrics integration
37
+ * @default true
38
+ */
39
+ circuitBreakerMetrics?: boolean;
40
+ }
41
+ /**
42
+ * Counter metric configuration
43
+ */
44
+ export interface CounterConfig extends Omit<CounterConfiguration<string>, 'registers'> {
45
+ name: string;
46
+ help: string;
47
+ labelNames?: string[];
48
+ }
49
+ /**
50
+ * Gauge metric configuration
51
+ */
52
+ export interface GaugeConfig extends Omit<GaugeConfiguration<string>, 'registers'> {
53
+ name: string;
54
+ help: string;
55
+ labelNames?: string[];
56
+ }
57
+ /**
58
+ * Histogram metric configuration
59
+ */
60
+ export interface HistogramConfig extends Omit<HistogramConfiguration<string>, 'registers'> {
61
+ name: string;
62
+ help: string;
63
+ labelNames?: string[];
64
+ buckets?: number[];
65
+ }
66
+ /**
67
+ * Summary metric configuration
68
+ */
69
+ export interface SummaryConfig extends Omit<SummaryConfiguration<string>, 'registers'> {
70
+ name: string;
71
+ help: string;
72
+ labelNames?: string[];
73
+ percentiles?: number[];
74
+ }
75
+ /**
76
+ * Metric instance types
77
+ */
78
+ export type MetricInstance = Counter<string> | Gauge<string> | Histogram<string> | Summary<string>;
79
+ /**
80
+ * Metric registry entry
81
+ */
82
+ export interface MetricEntry {
83
+ type: MetricType;
84
+ metric: MetricInstance;
85
+ config: CounterConfig | GaugeConfig | HistogramConfig | SummaryConfig;
86
+ }
87
+ /**
88
+ * Circuit breaker metric names
89
+ */
90
+ export declare const CIRCUIT_BREAKER_METRICS: {
91
+ readonly STATE: "circuit_breaker_state";
92
+ readonly CALLS_TOTAL: "circuit_breaker_calls_total";
93
+ readonly LATENCY_SECONDS: "circuit_breaker_latency_seconds";
94
+ readonly FAILURES_TOTAL: "circuit_breaker_failures_total";
95
+ readonly SUCCESSES_TOTAL: "circuit_breaker_successes_total";
96
+ readonly REJECTS_TOTAL: "circuit_breaker_rejects_total";
97
+ readonly TIMEOUTS_TOTAL: "circuit_breaker_timeouts_total";
98
+ };
99
+ /**
100
+ * Default histogram buckets for latency metrics (in seconds)
101
+ */
102
+ export declare const DEFAULT_LATENCY_BUCKETS: number[];
103
+ /**
104
+ * Default summary percentiles
105
+ */
106
+ export declare const DEFAULT_PERCENTILES: number[];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_PERCENTILES = exports.DEFAULT_LATENCY_BUCKETS = exports.CIRCUIT_BREAKER_METRICS = exports.MetricType = void 0;
4
+ /**
5
+ * Metric types supported by the metrics service
6
+ */
7
+ var MetricType;
8
+ (function (MetricType) {
9
+ MetricType["COUNTER"] = "counter";
10
+ MetricType["GAUGE"] = "gauge";
11
+ MetricType["HISTOGRAM"] = "histogram";
12
+ MetricType["SUMMARY"] = "summary";
13
+ })(MetricType || (exports.MetricType = MetricType = {}));
14
+ /**
15
+ * Circuit breaker metric names
16
+ */
17
+ exports.CIRCUIT_BREAKER_METRICS = {
18
+ STATE: 'circuit_breaker_state',
19
+ CALLS_TOTAL: 'circuit_breaker_calls_total',
20
+ LATENCY_SECONDS: 'circuit_breaker_latency_seconds',
21
+ FAILURES_TOTAL: 'circuit_breaker_failures_total',
22
+ SUCCESSES_TOTAL: 'circuit_breaker_successes_total',
23
+ REJECTS_TOTAL: 'circuit_breaker_rejects_total',
24
+ TIMEOUTS_TOTAL: 'circuit_breaker_timeouts_total',
25
+ };
26
+ /**
27
+ * Default histogram buckets for latency metrics (in seconds)
28
+ */
29
+ exports.DEFAULT_LATENCY_BUCKETS = [
30
+ 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
31
+ ];
32
+ /**
33
+ * Default summary percentiles
34
+ */
35
+ exports.DEFAULT_PERCENTILES = [0.5, 0.9, 0.95, 0.99];
@@ -0,0 +1,11 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { MetricsModuleOptions } from './metrics.interface';
3
+ export declare class MetricsModule {
4
+ /**
5
+ * Register the metrics module with options
6
+ *
7
+ * @param options - Module configuration options
8
+ * @returns Dynamic module
9
+ */
10
+ static register(options?: MetricsModuleOptions): DynamicModule;
11
+ }
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var MetricsModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MetricsModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const metrics_service_1 = require("./metrics.service");
13
+ const metrics_controller_1 = require("./metrics.controller");
14
+ let MetricsModule = MetricsModule_1 = class MetricsModule {
15
+ /**
16
+ * Register the metrics module with options
17
+ *
18
+ * @param options - Module configuration options
19
+ * @returns Dynamic module
20
+ */
21
+ static register(options = {}) {
22
+ return {
23
+ module: MetricsModule_1,
24
+ providers: [
25
+ {
26
+ provide: metrics_service_1.MetricsService,
27
+ useValue: new metrics_service_1.MetricsService(options),
28
+ },
29
+ ],
30
+ controllers: [metrics_controller_1.MetricsController],
31
+ exports: [metrics_service_1.MetricsService],
32
+ };
33
+ }
34
+ };
35
+ exports.MetricsModule = MetricsModule;
36
+ exports.MetricsModule = MetricsModule = MetricsModule_1 = __decorate([
37
+ (0, common_1.Global)(),
38
+ (0, common_1.Module)({})
39
+ ], MetricsModule);
@@ -0,0 +1,50 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import { Registry } from 'prom-client';
3
+ import { CounterConfig, GaugeConfig, HistogramConfig, SummaryConfig, MetricsModuleOptions } from './metrics.interface';
4
+ /**
5
+ * Prometheus Metrics Service
6
+ *
7
+ * Provides comprehensive metrics collection and exposure for monitoring
8
+ * and observability using Prometheus.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // Register a counter
13
+ * this.metricsService.registerCounter({
14
+ * name: 'api_requests_total',
15
+ * help: 'Total API requests',
16
+ * labelNames: ['method', 'endpoint'],
17
+ * });
18
+ *
19
+ * // Increment counter
20
+ * this.metricsService.incrementCounter('api_requests_total', { method: 'GET', endpoint: '/users' });
21
+ * ```
22
+ */
23
+ export declare class MetricsService implements OnModuleDestroy {
24
+ private readonly logger;
25
+ private readonly registry;
26
+ private readonly metricsRegistry;
27
+ private readonly metricsUpdater;
28
+ private defaultMetricsInterval?;
29
+ private options;
30
+ constructor(options?: MetricsModuleOptions);
31
+ registerCounter(config: CounterConfig): import("prom-client").Counter<string>;
32
+ registerGauge(config: GaugeConfig): import("prom-client").Gauge<string>;
33
+ registerHistogram(config: HistogramConfig): import("prom-client").Histogram<string>;
34
+ registerSummary(config: SummaryConfig): import("prom-client").Summary<string>;
35
+ incrementCounter(name: string, labels?: Record<string, string | number>, value?: number): void;
36
+ setGauge(name: string, value: number, labels?: Record<string, string | number>): void;
37
+ incrementGauge(name: string, labels?: Record<string, string | number>, value?: number): void;
38
+ decrementGauge(name: string, labels?: Record<string, string | number>, value?: number): void;
39
+ observeHistogram(name: string, value: number, labels?: Record<string, string | number>): void;
40
+ observeSummary(name: string, value: number, labels?: Record<string, string | number>): void;
41
+ getMetric(name: string): import("./metrics.interface").MetricEntry | undefined;
42
+ getMetrics(): Promise<string>;
43
+ getContentType(): string;
44
+ getRegistry(): Registry;
45
+ getMetricNames(): string[];
46
+ hasMetric(name: string): boolean;
47
+ resetMetrics(): void;
48
+ clearMetrics(): void;
49
+ onModuleDestroy(): Promise<void>;
50
+ }
@@ -0,0 +1,165 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var MetricsService_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.MetricsService = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const prom_client_1 = require("prom-client");
13
+ const metrics_registry_1 = require("./metrics-registry");
14
+ const metrics_updater_1 = require("./metrics-updater");
15
+ /**
16
+ * Prometheus Metrics Service
17
+ *
18
+ * Provides comprehensive metrics collection and exposure for monitoring
19
+ * and observability using Prometheus.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Register a counter
24
+ * this.metricsService.registerCounter({
25
+ * name: 'api_requests_total',
26
+ * help: 'Total API requests',
27
+ * labelNames: ['method', 'endpoint'],
28
+ * });
29
+ *
30
+ * // Increment counter
31
+ * this.metricsService.incrementCounter('api_requests_total', { method: 'GET', endpoint: '/users' });
32
+ * ```
33
+ */
34
+ let MetricsService = MetricsService_1 = class MetricsService {
35
+ logger = new common_1.Logger(MetricsService_1.name);
36
+ registry;
37
+ metricsRegistry;
38
+ metricsUpdater;
39
+ defaultMetricsInterval;
40
+ options;
41
+ constructor(options = {}) {
42
+ this.options = {
43
+ defaultMetrics: true,
44
+ prefix: '',
45
+ defaultLabels: {},
46
+ defaultMetricsInterval: 10000,
47
+ circuitBreakerMetrics: true,
48
+ ...options,
49
+ };
50
+ this.registry = new prom_client_1.Registry();
51
+ this.metricsRegistry = new metrics_registry_1.MetricsRegistry(this.registry, this.options.prefix);
52
+ this.metricsUpdater = new metrics_updater_1.MetricsUpdater();
53
+ // Set default labels
54
+ if (this.options.defaultLabels) {
55
+ this.registry.setDefaultLabels(this.options.defaultLabels);
56
+ }
57
+ // Collect default metrics
58
+ if (this.options.defaultMetrics) {
59
+ this.defaultMetricsInterval = (0, prom_client_1.collectDefaultMetrics)({
60
+ register: this.registry,
61
+ prefix: this.options.prefix,
62
+ });
63
+ this.logger.log('Default metrics collection enabled');
64
+ }
65
+ this.logger.log('Metrics service initialized');
66
+ }
67
+ // ==================== Registration Methods ====================
68
+ registerCounter(config) {
69
+ return this.metricsRegistry.registerCounter(config);
70
+ }
71
+ registerGauge(config) {
72
+ return this.metricsRegistry.registerGauge(config);
73
+ }
74
+ registerHistogram(config) {
75
+ return this.metricsRegistry.registerHistogram(config);
76
+ }
77
+ registerSummary(config) {
78
+ return this.metricsRegistry.registerSummary(config);
79
+ }
80
+ // ==================== Update Methods ====================
81
+ incrementCounter(name, labels, value = 1) {
82
+ const entry = this.metricsRegistry.getMetric(name);
83
+ if (!entry) {
84
+ throw new Error(`Counter '${name}' not found`);
85
+ }
86
+ this.metricsUpdater.incrementCounter(entry, labels, value);
87
+ }
88
+ setGauge(name, value, labels) {
89
+ const entry = this.metricsRegistry.getMetric(name);
90
+ if (!entry) {
91
+ throw new Error(`Gauge '${name}' not found`);
92
+ }
93
+ this.metricsUpdater.setGauge(entry, value, labels);
94
+ }
95
+ incrementGauge(name, labels, value = 1) {
96
+ const entry = this.metricsRegistry.getMetric(name);
97
+ if (!entry) {
98
+ throw new Error(`Gauge '${name}' not found`);
99
+ }
100
+ this.metricsUpdater.incrementGauge(entry, labels, value);
101
+ }
102
+ decrementGauge(name, labels, value = 1) {
103
+ const entry = this.metricsRegistry.getMetric(name);
104
+ if (!entry) {
105
+ throw new Error(`Gauge '${name}' not found`);
106
+ }
107
+ this.metricsUpdater.decrementGauge(entry, labels, value);
108
+ }
109
+ observeHistogram(name, value, labels) {
110
+ const entry = this.metricsRegistry.getMetric(name);
111
+ if (!entry) {
112
+ throw new Error(`Histogram '${name}' not found`);
113
+ }
114
+ this.metricsUpdater.observeHistogram(entry, value, labels);
115
+ }
116
+ observeSummary(name, value, labels) {
117
+ const entry = this.metricsRegistry.getMetric(name);
118
+ if (!entry) {
119
+ throw new Error(`Summary '${name}' not found`);
120
+ }
121
+ this.metricsUpdater.observeSummary(entry, value, labels);
122
+ }
123
+ // ==================== Query Methods ====================
124
+ getMetric(name) {
125
+ return this.metricsRegistry.getMetric(name);
126
+ }
127
+ async getMetrics() {
128
+ return this.registry.metrics();
129
+ }
130
+ getContentType() {
131
+ return this.registry.contentType;
132
+ }
133
+ getRegistry() {
134
+ return this.registry;
135
+ }
136
+ getMetricNames() {
137
+ return this.metricsRegistry.getMetricNames();
138
+ }
139
+ hasMetric(name) {
140
+ return this.metricsRegistry.hasMetric(name);
141
+ }
142
+ // ==================== Management Methods ====================
143
+ resetMetrics() {
144
+ this.registry.resetMetrics();
145
+ this.logger.log('All metrics reset');
146
+ }
147
+ clearMetrics() {
148
+ this.registry.clear();
149
+ this.metricsRegistry.clear();
150
+ this.logger.log('All metrics cleared');
151
+ }
152
+ // ==================== Lifecycle ====================
153
+ async onModuleDestroy() {
154
+ this.logger.log('Shutting down metrics service...');
155
+ if (this.defaultMetricsInterval) {
156
+ clearInterval(this.defaultMetricsInterval);
157
+ }
158
+ this.clearMetrics();
159
+ this.logger.log('Metrics service shut down');
160
+ }
161
+ };
162
+ exports.MetricsService = MetricsService;
163
+ exports.MetricsService = MetricsService = MetricsService_1 = __decorate([
164
+ (0, common_1.Injectable)()
165
+ ], MetricsService);
@@ -0,0 +1,16 @@
1
+ import CircuitBreaker from 'opossum';
2
+ /**
3
+ * Circuit Breaker Event Handler
4
+ *
5
+ * Handles all circuit breaker events and provides logging
6
+ */
7
+ export declare class CircuitBreakerEventHandler {
8
+ private readonly logger;
9
+ /**
10
+ * Set up event listeners for a circuit breaker
11
+ *
12
+ * @param breaker - Circuit breaker instance
13
+ * @param name - Circuit breaker name
14
+ */
15
+ setupEventListeners(breaker: CircuitBreaker, name: string): void;
16
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CircuitBreakerEventHandler = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const circuit_breaker_interface_1 = require("./circuit-breaker.interface");
6
+ /**
7
+ * Circuit Breaker Event Handler
8
+ *
9
+ * Handles all circuit breaker events and provides logging
10
+ */
11
+ class CircuitBreakerEventHandler {
12
+ logger = new common_1.Logger(CircuitBreakerEventHandler.name);
13
+ /**
14
+ * Set up event listeners for a circuit breaker
15
+ *
16
+ * @param breaker - Circuit breaker instance
17
+ * @param name - Circuit breaker name
18
+ */
19
+ setupEventListeners(breaker, name) {
20
+ // Success event
21
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.SUCCESS, (result, latency) => {
22
+ this.logger.debug(`[${name}] Success - Latency: ${latency}ms`);
23
+ });
24
+ // Failure event
25
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.FAILURE, (error) => {
26
+ this.logger.warn(`[${name}] Failure - Error: ${error.message}`);
27
+ });
28
+ // Timeout event
29
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.TIMEOUT, () => {
30
+ this.logger.warn(`[${name}] Timeout - Request exceeded timeout threshold`);
31
+ });
32
+ // Reject event (circuit is open)
33
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.REJECT, () => {
34
+ this.logger.warn(`[${name}] Reject - Circuit is open, request rejected`);
35
+ });
36
+ // Circuit opened
37
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.OPEN, () => {
38
+ this.logger.error(`[${name}] Circuit OPENED - Too many failures detected`);
39
+ });
40
+ // Circuit closed
41
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.CLOSE, () => {
42
+ this.logger.log(`[${name}] Circuit CLOSED - Service recovered`);
43
+ });
44
+ // Circuit half-open
45
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.HALF_OPEN, () => {
46
+ this.logger.log(`[${name}] Circuit HALF-OPEN - Testing service recovery`);
47
+ });
48
+ // Fallback executed
49
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.FALLBACK, (result) => {
50
+ this.logger.debug(`[${name}] Fallback executed`);
51
+ });
52
+ // Semaphore locked (too many concurrent requests)
53
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.SEMAPHORE_LOCKED, () => {
54
+ this.logger.warn(`[${name}] Semaphore locked - Too many concurrent requests`);
55
+ });
56
+ // Health check failed
57
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.HEALTH_CHECK_FAILED, () => {
58
+ this.logger.warn(`[${name}] Health check failed`);
59
+ });
60
+ // Cache hit
61
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.CACHE_HIT, () => {
62
+ this.logger.debug(`[${name}] Cache hit`);
63
+ });
64
+ // Cache miss
65
+ breaker.on(circuit_breaker_interface_1.CircuitBreakerEvent.CACHE_MISS, () => {
66
+ this.logger.debug(`[${name}] Cache miss`);
67
+ });
68
+ }
69
+ }
70
+ exports.CircuitBreakerEventHandler = CircuitBreakerEventHandler;
@@ -0,0 +1,19 @@
1
+ import { CircuitBreakerOptions, CircuitBreakerInstance } from './circuit-breaker.interface';
2
+ /**
3
+ * Circuit Breaker Factory
4
+ *
5
+ * Responsible for creating and configuring circuit breaker instances
6
+ */
7
+ export declare class CircuitBreakerFactory {
8
+ private readonly logger;
9
+ private readonly eventHandler;
10
+ /**
11
+ * Create a new circuit breaker instance
12
+ *
13
+ * @param name - Unique identifier for the circuit breaker
14
+ * @param action - The async function to be protected
15
+ * @param options - Circuit breaker configuration options
16
+ * @returns Circuit breaker instance
17
+ */
18
+ create<T = any, R = any>(name: string, action: (...args: T[]) => Promise<R>, options?: CircuitBreakerOptions): CircuitBreakerInstance<T, R>;
19
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.CircuitBreakerFactory = void 0;
7
+ const common_1 = require("@nestjs/common");
8
+ const opossum_1 = __importDefault(require("opossum"));
9
+ const circuit_breaker_event_handler_1 = require("./circuit-breaker-event-handler");
10
+ /**
11
+ * Circuit Breaker Factory
12
+ *
13
+ * Responsible for creating and configuring circuit breaker instances
14
+ */
15
+ class CircuitBreakerFactory {
16
+ logger = new common_1.Logger(CircuitBreakerFactory.name);
17
+ eventHandler = new circuit_breaker_event_handler_1.CircuitBreakerEventHandler();
18
+ /**
19
+ * Create a new circuit breaker instance
20
+ *
21
+ * @param name - Unique identifier for the circuit breaker
22
+ * @param action - The async function to be protected
23
+ * @param options - Circuit breaker configuration options
24
+ * @returns Circuit breaker instance
25
+ */
26
+ create(name, action, options = {}) {
27
+ const defaultOptions = {
28
+ timeout: 10000, // 10 seconds
29
+ errorThresholdPercentage: 50, // 50% error rate
30
+ resetTimeout: 30000, // 30 seconds
31
+ rollingCountTimeout: 10000, // 10 seconds
32
+ rollingCountBuckets: 10,
33
+ capacity: 100,
34
+ enableSnapshots: true,
35
+ volumeThreshold: 5, // Minimum number of requests before circuit can open
36
+ name,
37
+ ...options,
38
+ };
39
+ const breaker = new opossum_1.default(action, defaultOptions);
40
+ // Set up event listeners for monitoring and logging
41
+ this.eventHandler.setupEventListeners(breaker, name);
42
+ const instance = {
43
+ breaker,
44
+ name,
45
+ options: defaultOptions,
46
+ };
47
+ this.logger.log(`Circuit breaker '${name}' created successfully`);
48
+ return instance;
49
+ }
50
+ }
51
+ exports.CircuitBreakerFactory = CircuitBreakerFactory;
@@ -0,0 +1,37 @@
1
+ import CircuitBreaker from 'opossum';
2
+ import { CircuitBreakerStats, CircuitState, CircuitBreakerInstance } from './circuit-breaker.interface';
3
+ /**
4
+ * Circuit Breaker Statistics Service
5
+ *
6
+ * Handles statistics and state management for circuit breakers
7
+ */
8
+ export declare class CircuitBreakerStatsService {
9
+ /**
10
+ * Get statistics for a circuit breaker
11
+ *
12
+ * @param instance - Circuit breaker instance
13
+ * @returns Circuit breaker statistics
14
+ */
15
+ getStats(instance: CircuitBreakerInstance): CircuitBreakerStats;
16
+ /**
17
+ * Get all circuit breaker statistics
18
+ *
19
+ * @param breakers - Map of circuit breaker instances
20
+ * @returns Map of circuit breaker names to their statistics
21
+ */
22
+ getAllStats(breakers: Map<string, CircuitBreakerInstance>): Map<string, CircuitBreakerStats>;
23
+ /**
24
+ * Get the current state of a circuit breaker
25
+ *
26
+ * @param breaker - Circuit breaker instance
27
+ * @returns Current circuit state
28
+ */
29
+ getState(breaker: CircuitBreaker): CircuitState;
30
+ /**
31
+ * Check if a circuit breaker is open
32
+ *
33
+ * @param breaker - Circuit breaker instance
34
+ * @returns True if circuit is open
35
+ */
36
+ isOpen(breaker: CircuitBreaker): boolean;
37
+ }
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CircuitBreakerStatsService = void 0;
4
+ const circuit_breaker_interface_1 = require("./circuit-breaker.interface");
5
+ /**
6
+ * Circuit Breaker Statistics Service
7
+ *
8
+ * Handles statistics and state management for circuit breakers
9
+ */
10
+ class CircuitBreakerStatsService {
11
+ /**
12
+ * Get statistics for a circuit breaker
13
+ *
14
+ * @param instance - Circuit breaker instance
15
+ * @returns Circuit breaker statistics
16
+ */
17
+ getStats(instance) {
18
+ const stats = instance.breaker.stats;
19
+ return {
20
+ fires: stats.fires,
21
+ failures: stats.failures,
22
+ successes: stats.successes,
23
+ rejects: stats.rejects,
24
+ timeouts: stats.timeouts,
25
+ cacheHits: stats.cacheHits,
26
+ cacheMisses: stats.cacheMisses,
27
+ semaphoreRejections: stats.semaphoreRejections,
28
+ percentiles: stats.percentiles,
29
+ latencyMean: stats.latencyMean,
30
+ latencyTimes: stats.latencyTimes,
31
+ };
32
+ }
33
+ /**
34
+ * Get all circuit breaker statistics
35
+ *
36
+ * @param breakers - Map of circuit breaker instances
37
+ * @returns Map of circuit breaker names to their statistics
38
+ */
39
+ getAllStats(breakers) {
40
+ const allStats = new Map();
41
+ for (const [name, instance] of breakers.entries()) {
42
+ allStats.set(name, this.getStats(instance));
43
+ }
44
+ return allStats;
45
+ }
46
+ /**
47
+ * Get the current state of a circuit breaker
48
+ *
49
+ * @param breaker - Circuit breaker instance
50
+ * @returns Current circuit state
51
+ */
52
+ getState(breaker) {
53
+ if (breaker.opened)
54
+ return circuit_breaker_interface_1.CircuitState.OPEN;
55
+ if (breaker.halfOpen)
56
+ return circuit_breaker_interface_1.CircuitState.HALF_OPEN;
57
+ return circuit_breaker_interface_1.CircuitState.CLOSED;
58
+ }
59
+ /**
60
+ * Check if a circuit breaker is open
61
+ *
62
+ * @param breaker - Circuit breaker instance
63
+ * @returns True if circuit is open
64
+ */
65
+ isOpen(breaker) {
66
+ return breaker.opened;
67
+ }
68
+ }
69
+ exports.CircuitBreakerStatsService = CircuitBreakerStatsService;