tiryaq-shared 1.2.30 → 1.3.2
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/kafka/broker-parser.d.ts +54 -0
- package/dist/kafka/broker-parser.d.ts.map +1 -0
- package/dist/kafka/broker-parser.js +191 -0
- package/dist/kafka/broker-parser.js.map +1 -0
- package/dist/kafka/circuit-breaker.provider.d.ts +113 -0
- package/dist/kafka/circuit-breaker.provider.d.ts.map +1 -0
- package/dist/kafka/circuit-breaker.provider.js +230 -0
- package/dist/kafka/circuit-breaker.provider.js.map +1 -0
- package/dist/kafka/dlq-handler.d.ts +102 -0
- package/dist/kafka/dlq-handler.d.ts.map +1 -0
- package/dist/kafka/dlq-handler.js +220 -0
- package/dist/kafka/dlq-handler.js.map +1 -0
- package/dist/kafka/health-check.provider.d.ts +78 -0
- package/dist/kafka/health-check.provider.d.ts.map +1 -0
- package/dist/kafka/health-check.provider.js +170 -0
- package/dist/kafka/health-check.provider.js.map +1 -0
- package/dist/kafka/index.d.ts +15 -0
- package/dist/kafka/index.d.ts.map +1 -0
- package/dist/kafka/index.js +41 -0
- package/dist/kafka/index.js.map +1 -0
- package/dist/kafka/kafka-config.manager.d.ts +92 -0
- package/dist/kafka/kafka-config.manager.d.ts.map +1 -0
- package/dist/kafka/kafka-config.manager.js +306 -0
- package/dist/kafka/kafka-config.manager.js.map +1 -0
- package/dist/kafka/kafka-logger.d.ts +125 -0
- package/dist/kafka/kafka-logger.d.ts.map +1 -0
- package/dist/kafka/kafka-logger.js +204 -0
- package/dist/kafka/kafka-logger.js.map +1 -0
- package/dist/kafka/subscription-registry.d.ts +141 -0
- package/dist/kafka/subscription-registry.d.ts.map +1 -0
- package/dist/kafka/subscription-registry.js +219 -0
- package/dist/kafka/subscription-registry.js.map +1 -0
- package/dist/kafka/types.d.ts +163 -0
- package/dist/kafka/types.d.ts.map +1 -0
- package/dist/kafka/types.js +19 -0
- package/dist/kafka/types.js.map +1 -0
- package/dist/message-patterns.d.ts +2 -0
- package/dist/message-patterns.d.ts.map +1 -1
- package/dist/message-patterns.js +3 -0
- package/dist/message-patterns.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './constants';
|
|
|
7
7
|
export * from './filters/global-exception.filter';
|
|
8
8
|
export * from './filters/validation-exception.filter';
|
|
9
9
|
export * from './filters/microservice-exception.filter';
|
|
10
|
+
export * from './kafka';
|
|
10
11
|
export { User, UserAddress, RegisterUserDto, LoginDto, UserSettings, SearchQuery, SearchFilters, SortOptions, Pharmacy, Medicine, PharmacyOrder, OrderItem, OpeningHours, Location, Doctor, TimeSlot, Appointment, Prescription, TeleMedicineSession, ChatMessage, LabTest, Lab, LabAppointment, LabReport, Wallet, PaymentCard, Transaction, DoctorWallet, WalletTransaction, WithdrawalRequest, AreebaPaymentRequest, AreebaWithdrawalRequest, NurseWallet, NurseWalletTransaction, NurseWithdrawalRequest, LabWallet, LabWalletTransaction, LabWithdrawalRequest, PhysiotherapyWallet, PhysiotherapyWalletTransaction, PhysiotherapyWithdrawalRequest, Notification, NotificationSettings, ApiResponse, PaginatedResponse, StandardizedServiceProvider, CommissionMessage, AdminFeeMessage, ProviderCommissionMessage, ProviderListRequest, ProviderListResponse, ProviderInfo, ServiceProviderTypesResponse, CommissionRateRequest, CommissionCalculationRequest, CommissionResolutionRequest, CommissionBreakdownResponse, CommissionResolutionResponse, AdminWallet, AdminWalletTransaction, AdminWithdrawalRequest, AdminTransactionType, WithdrawalStatus, TransactionStatus, AdminFeeCollectionParams, TransactionFilters, AnalyticsFilters, WithdrawalFilters, WithdrawalRequestParams, RevenueAnalytics, GrowthTrend, ServicePerformance, FinancialReport, ReportPeriod, ReportSummary, ServiceBreakdown, TransactionSummary, WithdrawalSummary, ReportParams, AdminWalletErrorResponse, AdminFeeCollectionEvent } from './interfaces';
|
|
11
12
|
export { AUTH_PATTERNS, AUTH_REPLY_PATTERNS, CONSULTATION_AND_PHARMACY_PATTERNS, MEDIA_PATTERNS, MEDIA_REPLY_PATTERNS, SETTINGS_PATTERNS, SEARCH_PATTERNS, PHARMACY_PATTERNS, CONSULTATION_PATTERNS, TELEMEDICINE_PATTERNS, LAB_PATTERNS, PAYMENT_PATTERNS, NOTIFICATION_PATTERNS, EVENT_PATTERNS, UserRegisteredEvent, OrderCreatedEvent, AppointmentBookedEvent, PaymentProcessedEvent, NotificationEvent, CommissionUpdatedEvent, AdminFeeUpdatedEvent, ProviderCommissionUpdatedEvent, MessageValidationUtils, KAFKA_CONFIG, SERVICE_PORTS } from './message-patterns';
|
|
12
13
|
export { COMMON_ERROR_CODES, AUTH_ERROR_CODES, PHARMACY_ERROR_CODES, CONSULTATION_ERROR_CODES, CONSULTATION_AND_PHARMACY_ERROR_CODES, PAYMENT_ERROR_CODES, LAB_ERROR_CODES, NOTIFICATION_ERROR_CODES, SEARCH_ERROR_CODES, MEDIA_ERROR_CODES, SUCCESS_CODES, ErrorCode, SuccessCode } from './error-codes';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,mCAAmC,CAAC;AAClD,cAAc,uCAAuC,CAAC;AACtD,cAAc,yCAAyC,CAAC;AACxD,cAAc,SAAS,CAAC;AAGxB,OAAO,EAEL,IAAI,EACJ,WAAW,EACX,eAAe,EACf,QAAQ,EAGR,YAAY,EAGZ,WAAW,EACX,aAAa,EACb,WAAW,EAGX,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,SAAS,EACT,YAAY,EACZ,QAAQ,EAGR,MAAM,EACN,QAAQ,EACR,WAAW,EACX,YAAY,EAGZ,mBAAmB,EACnB,WAAW,EAGX,OAAO,EACP,GAAG,EACH,cAAc,EACd,SAAS,EAGT,MAAM,EACN,WAAW,EACX,WAAW,EAGX,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,EAGvB,WAAW,EACX,sBAAsB,EACtB,sBAAsB,EAGtB,SAAS,EACT,oBAAoB,EACpB,oBAAoB,EAGpB,mBAAmB,EACnB,8BAA8B,EAC9B,8BAA8B,EAG9B,YAAY,EACZ,oBAAoB,EAGpB,WAAW,EACX,iBAAiB,EAGjB,2BAA2B,EAG3B,iBAAiB,EACjB,eAAe,EACf,yBAAyB,EACzB,mBAAmB,EACnB,oBAAoB,EACpB,YAAY,EACZ,4BAA4B,EAC5B,qBAAqB,EACrB,4BAA4B,EAC5B,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAG5B,WAAW,EACX,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,uBAAuB,EACvB,gBAAgB,EAChB,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,aAAa,EACb,mBAAmB,EACnB,kCAAkC,EAClC,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,qBAAqB,EACrB,cAAc,EAGd,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,EACtB,qBAAqB,EACrB,iBAAiB,EAGjB,sBAAsB,EACtB,oBAAoB,EACpB,8BAA8B,EAG9B,sBAAsB,EAGtB,YAAY,EACZ,aAAa,EACd,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EAEL,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,wBAAwB,EACxB,qCAAqC,EACrC,mBAAmB,EACnB,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,iBAAiB,EAGjB,aAAa,EAGb,SAAS,EACT,WAAW,EACZ,MAAM,eAAe,CAAC;AAEvB,OAAO,EAEL,aAAa,EACd,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAEL,aAAa,EAGb,KAAK,eAAe,EACpB,KAAK,qCAAqC,EAC1C,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,GACjC,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -25,6 +25,7 @@ __exportStar(require("./constants"), exports);
|
|
|
25
25
|
__exportStar(require("./filters/global-exception.filter"), exports);
|
|
26
26
|
__exportStar(require("./filters/validation-exception.filter"), exports);
|
|
27
27
|
__exportStar(require("./filters/microservice-exception.filter"), exports);
|
|
28
|
+
__exportStar(require("./kafka"), exports);
|
|
28
29
|
// Named exports for better tree-shaking and explicit imports
|
|
29
30
|
var interfaces_1 = require("./interfaces");
|
|
30
31
|
// Standardized service provider types
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,kCAAkC;AAClC,+CAA6B;AAC7B,qDAAmC;AACnC,gDAA8B;AAC9B,mDAAiC;AACjC,kDAAgC;AAChC,8CAA4B;AAC5B,oEAAkD;AAClD,wEAAsD;AACtD,0EAAwD;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,kCAAkC;AAClC,+CAA6B;AAC7B,qDAAmC;AACnC,gDAA8B;AAC9B,mDAAiC;AACjC,kDAAgC;AAChC,8CAA4B;AAC5B,oEAAkD;AAClD,wEAAsD;AACtD,0EAAwD;AACxD,0CAAwB;AAExB,6DAA6D;AAC7D,2CAmHsB;AAzCpB,sCAAsC;AACtC,yHAAA,2BAA2B,OAAA;AAoB3B,kHAAA,oBAAoB,OAAA;AACpB,8GAAA,gBAAgB,OAAA;AAChB,+GAAA,iBAAiB,OAAA;AAoBnB,uDAmC4B;AAlC1B,mBAAmB;AACnB,iHAAA,aAAa,OAAA;AACb,uHAAA,mBAAmB,OAAA;AACnB,sIAAA,kCAAkC,OAAA;AAClC,kHAAA,cAAc,OAAA;AACd,wHAAA,oBAAoB,OAAA;AACpB,qHAAA,iBAAiB,OAAA;AACjB,mHAAA,eAAe,OAAA;AACf,qHAAA,iBAAiB,OAAA;AACjB,yHAAA,qBAAqB,OAAA;AACrB,yHAAA,qBAAqB,OAAA;AACrB,gHAAA,YAAY,OAAA;AACZ,oHAAA,gBAAgB,OAAA;AAChB,yHAAA,qBAAqB,OAAA;AACrB,kHAAA,cAAc,OAAA;AAcd,+BAA+B;AAC/B,0HAAA,sBAAsB,OAAA;AAEtB,gBAAgB;AAChB,gHAAA,YAAY,OAAA;AACZ,iHAAA,aAAa,OAAA;AAGf,6CAmBuB;AAlBrB,cAAc;AACd,iHAAA,kBAAkB,OAAA;AAClB,+GAAA,gBAAgB,OAAA;AAChB,mHAAA,oBAAoB,OAAA;AACpB,uHAAA,wBAAwB,OAAA;AACxB,oIAAA,qCAAqC,OAAA;AACrC,kHAAA,mBAAmB,OAAA;AACnB,8GAAA,eAAe,OAAA;AACf,uHAAA,wBAAwB,OAAA;AACxB,iHAAA,kBAAkB,OAAA;AAClB,gHAAA,iBAAiB,OAAA;AAEjB,gBAAgB;AAChB,4GAAA,aAAa,OAAA;AAOf,mDAG0B;AAFxB,qBAAqB;AACrB,+GAAA,aAAa,OAAA;AAGf,iDAYyB;AAXvB,mBAAmB;AACnB,8GAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broker Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses and validates Kafka broker addresses from environment variables.
|
|
5
|
+
* Supports both local (localhost:9092) and MSK (AWS) formats.
|
|
6
|
+
*/
|
|
7
|
+
import { Logger } from '@nestjs/common';
|
|
8
|
+
import { BrokerValidationResult } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* BrokerParser class for parsing and validating Kafka broker addresses
|
|
11
|
+
*/
|
|
12
|
+
export declare class BrokerParser {
|
|
13
|
+
private logger;
|
|
14
|
+
constructor(logger?: Logger);
|
|
15
|
+
/**
|
|
16
|
+
* Parse brokers from environment variable
|
|
17
|
+
* Supports both JSON (MSK) and comma-separated (local) formats
|
|
18
|
+
*
|
|
19
|
+
* @param kafkaBroker - Broker string from environment variable
|
|
20
|
+
* @param mode - Kafka mode ('local' or 'msk')
|
|
21
|
+
* @returns Array of broker addresses
|
|
22
|
+
*/
|
|
23
|
+
parse(kafkaBroker: string, mode: 'local' | 'msk'): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Validate single broker address format
|
|
26
|
+
* Broker must follow host:port format with port between 1 and 65535
|
|
27
|
+
*
|
|
28
|
+
* @param broker - Broker address to validate
|
|
29
|
+
* @returns Validation result with error message if invalid
|
|
30
|
+
*/
|
|
31
|
+
validateBroker(broker: string): BrokerValidationResult;
|
|
32
|
+
/**
|
|
33
|
+
* Parse JSON configuration for MSK
|
|
34
|
+
* Expected format:
|
|
35
|
+
* {
|
|
36
|
+
* "kafka_broker": "broker1:9092,broker2:9092",
|
|
37
|
+
* "kafka_sasl_mechanism": "plain",
|
|
38
|
+
* "kafka_sasl_username": "username",
|
|
39
|
+
* "kafka_sasl_password": "password"
|
|
40
|
+
* }
|
|
41
|
+
*
|
|
42
|
+
* @param jsonString - JSON string to parse
|
|
43
|
+
* @returns Parsed configuration with brokers and SASL settings
|
|
44
|
+
*/
|
|
45
|
+
parseJsonConfig(jsonString: string): {
|
|
46
|
+
brokers: string[];
|
|
47
|
+
sasl?: {
|
|
48
|
+
mechanism: string;
|
|
49
|
+
username: string;
|
|
50
|
+
password: string;
|
|
51
|
+
};
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=broker-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-parser.d.ts","sourceRoot":"","sources":["../../src/kafka/broker-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAEjD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,CAAC,EAAE,MAAM;IAI3B;;;;;;;OAOG;IACH,KAAK,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,EAAE;IA2C3D;;;;;;OAMG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,sBAAsB;IAyDtD;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG;QACnC,OAAO,EAAE,MAAM,EAAE,CAAC;QAClB,IAAI,CAAC,EAAE;YACL,SAAS,EAAE,MAAM,CAAC;YAClB,QAAQ,EAAE,MAAM,CAAC;YACjB,QAAQ,EAAE,MAAM,CAAC;SAClB,CAAC;KACH;CAiEF"}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Broker Parser
|
|
4
|
+
*
|
|
5
|
+
* Parses and validates Kafka broker addresses from environment variables.
|
|
6
|
+
* Supports both local (localhost:9092) and MSK (AWS) formats.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.BrokerParser = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
/**
|
|
12
|
+
* BrokerParser class for parsing and validating Kafka broker addresses
|
|
13
|
+
*/
|
|
14
|
+
class BrokerParser {
|
|
15
|
+
constructor(logger) {
|
|
16
|
+
this.logger = logger || new common_1.Logger('BrokerParser');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Parse brokers from environment variable
|
|
20
|
+
* Supports both JSON (MSK) and comma-separated (local) formats
|
|
21
|
+
*
|
|
22
|
+
* @param kafkaBroker - Broker string from environment variable
|
|
23
|
+
* @param mode - Kafka mode ('local' or 'msk')
|
|
24
|
+
* @returns Array of broker addresses
|
|
25
|
+
*/
|
|
26
|
+
parse(kafkaBroker, mode) {
|
|
27
|
+
if (!kafkaBroker || kafkaBroker.trim() === '') {
|
|
28
|
+
if (mode === 'local') {
|
|
29
|
+
this.logger.log('No KAFKA_BROKER provided, using default localhost:9092');
|
|
30
|
+
return ['localhost:9092'];
|
|
31
|
+
}
|
|
32
|
+
throw new Error('KAFKA_BROKER environment variable is required for MSK mode');
|
|
33
|
+
}
|
|
34
|
+
// Try JSON parsing first for MSK format
|
|
35
|
+
if (mode === 'msk') {
|
|
36
|
+
try {
|
|
37
|
+
const config = this.parseJsonConfig(kafkaBroker);
|
|
38
|
+
return config.brokers;
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
42
|
+
this.logger.error(`Failed to parse MSK JSON configuration: ${errorMessage}`);
|
|
43
|
+
throw new Error(`Invalid MSK configuration: ${errorMessage}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Fall back to comma-separated string parsing for local mode
|
|
47
|
+
const brokers = kafkaBroker
|
|
48
|
+
.split(',')
|
|
49
|
+
.map(broker => broker.trim())
|
|
50
|
+
.filter(broker => broker.length > 0);
|
|
51
|
+
// Validate each broker
|
|
52
|
+
const invalidBrokers = [];
|
|
53
|
+
for (const broker of brokers) {
|
|
54
|
+
const validation = this.validateBroker(broker);
|
|
55
|
+
if (!validation.valid) {
|
|
56
|
+
invalidBrokers.push(`${broker}: ${validation.error}`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (invalidBrokers.length > 0) {
|
|
60
|
+
throw new Error(`Invalid broker addresses: ${invalidBrokers.join(', ')}`);
|
|
61
|
+
}
|
|
62
|
+
return brokers;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Validate single broker address format
|
|
66
|
+
* Broker must follow host:port format with port between 1 and 65535
|
|
67
|
+
*
|
|
68
|
+
* @param broker - Broker address to validate
|
|
69
|
+
* @returns Validation result with error message if invalid
|
|
70
|
+
*/
|
|
71
|
+
validateBroker(broker) {
|
|
72
|
+
if (!broker || broker.trim() === '') {
|
|
73
|
+
return {
|
|
74
|
+
valid: false,
|
|
75
|
+
broker,
|
|
76
|
+
error: 'Broker address cannot be empty'
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
const trimmedBroker = broker.trim();
|
|
80
|
+
// Check for host:port format
|
|
81
|
+
const parts = trimmedBroker.split(':');
|
|
82
|
+
if (parts.length !== 2) {
|
|
83
|
+
return {
|
|
84
|
+
valid: false,
|
|
85
|
+
broker: trimmedBroker,
|
|
86
|
+
error: 'Broker must follow host:port format'
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const [host, portStr] = parts;
|
|
90
|
+
// Validate host is not empty
|
|
91
|
+
if (!host || host.trim() === '') {
|
|
92
|
+
return {
|
|
93
|
+
valid: false,
|
|
94
|
+
broker: trimmedBroker,
|
|
95
|
+
error: 'Host cannot be empty'
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
// Validate port is numeric
|
|
99
|
+
const port = parseInt(portStr, 10);
|
|
100
|
+
if (isNaN(port)) {
|
|
101
|
+
return {
|
|
102
|
+
valid: false,
|
|
103
|
+
broker: trimmedBroker,
|
|
104
|
+
error: 'Port must be a number'
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
// Validate port range (1-65535)
|
|
108
|
+
if (port < 1 || port > 65535) {
|
|
109
|
+
return {
|
|
110
|
+
valid: false,
|
|
111
|
+
broker: trimmedBroker,
|
|
112
|
+
error: 'Port must be between 1 and 65535'
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
return {
|
|
116
|
+
valid: true,
|
|
117
|
+
broker: trimmedBroker
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Parse JSON configuration for MSK
|
|
122
|
+
* Expected format:
|
|
123
|
+
* {
|
|
124
|
+
* "kafka_broker": "broker1:9092,broker2:9092",
|
|
125
|
+
* "kafka_sasl_mechanism": "plain",
|
|
126
|
+
* "kafka_sasl_username": "username",
|
|
127
|
+
* "kafka_sasl_password": "password"
|
|
128
|
+
* }
|
|
129
|
+
*
|
|
130
|
+
* @param jsonString - JSON string to parse
|
|
131
|
+
* @returns Parsed configuration with brokers and SASL settings
|
|
132
|
+
*/
|
|
133
|
+
parseJsonConfig(jsonString) {
|
|
134
|
+
let config;
|
|
135
|
+
try {
|
|
136
|
+
config = JSON.parse(jsonString);
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
throw new Error('KAFKA_BROKER must be valid JSON for MSK mode');
|
|
140
|
+
}
|
|
141
|
+
// Validate required fields
|
|
142
|
+
if (!config.kafka_broker) {
|
|
143
|
+
throw new Error('MSK configuration must include kafka_broker field');
|
|
144
|
+
}
|
|
145
|
+
// Parse broker addresses
|
|
146
|
+
const brokerString = config.kafka_broker;
|
|
147
|
+
const brokers = brokerString
|
|
148
|
+
.split(',')
|
|
149
|
+
.map((broker) => broker.trim())
|
|
150
|
+
.filter((broker) => broker.length > 0);
|
|
151
|
+
if (brokers.length === 0) {
|
|
152
|
+
throw new Error('MSK configuration must include at least one broker address');
|
|
153
|
+
}
|
|
154
|
+
// Validate each broker
|
|
155
|
+
const invalidBrokers = [];
|
|
156
|
+
for (const broker of brokers) {
|
|
157
|
+
const validation = this.validateBroker(broker);
|
|
158
|
+
if (!validation.valid) {
|
|
159
|
+
invalidBrokers.push(`${broker}: ${validation.error}`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (invalidBrokers.length > 0) {
|
|
163
|
+
throw new Error(`Invalid broker addresses in MSK config: ${invalidBrokers.join(', ')}`);
|
|
164
|
+
}
|
|
165
|
+
// Parse SASL configuration if present
|
|
166
|
+
let sasl;
|
|
167
|
+
if (config.kafka_sasl_mechanism || config.kafka_sasl_username || config.kafka_sasl_password) {
|
|
168
|
+
// If any SASL field is present, all must be present
|
|
169
|
+
if (!config.kafka_sasl_mechanism) {
|
|
170
|
+
throw new Error('MSK configuration with SASL must include kafka_sasl_mechanism');
|
|
171
|
+
}
|
|
172
|
+
if (!config.kafka_sasl_username) {
|
|
173
|
+
throw new Error('MSK configuration with SASL must include kafka_sasl_username');
|
|
174
|
+
}
|
|
175
|
+
if (!config.kafka_sasl_password) {
|
|
176
|
+
throw new Error('MSK configuration with SASL must include kafka_sasl_password');
|
|
177
|
+
}
|
|
178
|
+
sasl = {
|
|
179
|
+
mechanism: config.kafka_sasl_mechanism,
|
|
180
|
+
username: config.kafka_sasl_username,
|
|
181
|
+
password: config.kafka_sasl_password
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
brokers,
|
|
186
|
+
sasl
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.BrokerParser = BrokerParser;
|
|
191
|
+
//# sourceMappingURL=broker-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"broker-parser.js","sourceRoot":"","sources":["../../src/kafka/broker-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit Breaker Provider
|
|
3
|
+
*
|
|
4
|
+
* Implements the circuit breaker pattern for inter-service Kafka calls.
|
|
5
|
+
* Prevents cascading failures by stopping requests to failing services.
|
|
6
|
+
*
|
|
7
|
+
* State Machine:
|
|
8
|
+
* - CLOSED: Normal operation, requests pass through
|
|
9
|
+
* - OPEN: Service is failing, requests are rejected immediately
|
|
10
|
+
* - HALF_OPEN: Testing if service has recovered, limited requests allowed
|
|
11
|
+
*/
|
|
12
|
+
import { Logger } from '@nestjs/common';
|
|
13
|
+
import { CircuitBreakerConfig, CircuitBreakerStats } from './types';
|
|
14
|
+
/**
|
|
15
|
+
* CircuitBreakerProvider implements the circuit breaker pattern
|
|
16
|
+
*
|
|
17
|
+
* Features:
|
|
18
|
+
* - Automatic state transitions based on failure/success rates
|
|
19
|
+
* - Configurable thresholds and timeouts
|
|
20
|
+
* - Structured logging of state changes
|
|
21
|
+
* - Statistics tracking for monitoring
|
|
22
|
+
*/
|
|
23
|
+
export declare class CircuitBreakerProvider {
|
|
24
|
+
private serviceName;
|
|
25
|
+
private logger;
|
|
26
|
+
private config;
|
|
27
|
+
private state;
|
|
28
|
+
private failures;
|
|
29
|
+
private successes;
|
|
30
|
+
private lastFailureTime?;
|
|
31
|
+
private lastStateChange;
|
|
32
|
+
private halfOpenAttempts;
|
|
33
|
+
private totalRequests;
|
|
34
|
+
private totalFailures;
|
|
35
|
+
private failureTimestamps;
|
|
36
|
+
/**
|
|
37
|
+
* Create a new CircuitBreakerProvider instance
|
|
38
|
+
*
|
|
39
|
+
* @param serviceName - Name of the target service being protected
|
|
40
|
+
* @param config - Optional circuit breaker configuration (uses defaults if not provided)
|
|
41
|
+
* @param logger - Optional NestJS Logger instance
|
|
42
|
+
*/
|
|
43
|
+
constructor(serviceName: string, config?: Partial<CircuitBreakerConfig>, logger?: Logger);
|
|
44
|
+
/**
|
|
45
|
+
* Execute a function with circuit breaker protection
|
|
46
|
+
*
|
|
47
|
+
* @param fn - Async function to execute
|
|
48
|
+
* @returns Promise resolving to the function result
|
|
49
|
+
* @throws Error if circuit is open or function execution fails
|
|
50
|
+
*/
|
|
51
|
+
execute<T>(fn: () => Promise<T>): Promise<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Get current circuit breaker statistics
|
|
54
|
+
*
|
|
55
|
+
* @returns Circuit breaker statistics object
|
|
56
|
+
*/
|
|
57
|
+
getStats(): CircuitBreakerStats;
|
|
58
|
+
/**
|
|
59
|
+
* Manually reset circuit breaker to closed state
|
|
60
|
+
*
|
|
61
|
+
* Useful for administrative operations or testing
|
|
62
|
+
*/
|
|
63
|
+
reset(): void;
|
|
64
|
+
/**
|
|
65
|
+
* Record successful execution
|
|
66
|
+
*
|
|
67
|
+
* Updates success counter and handles state transitions from HALF_OPEN to CLOSED
|
|
68
|
+
*/
|
|
69
|
+
private recordSuccess;
|
|
70
|
+
/**
|
|
71
|
+
* Record failed execution
|
|
72
|
+
*
|
|
73
|
+
* Updates failure counter and handles state transitions to OPEN
|
|
74
|
+
*/
|
|
75
|
+
private recordFailure;
|
|
76
|
+
/**
|
|
77
|
+
* Check if circuit should open based on failure threshold
|
|
78
|
+
*
|
|
79
|
+
* @returns True if circuit should open, false otherwise
|
|
80
|
+
*/
|
|
81
|
+
private shouldOpen;
|
|
82
|
+
/**
|
|
83
|
+
* Check if circuit should transition from OPEN to HALF_OPEN
|
|
84
|
+
*
|
|
85
|
+
* Called before each execution when circuit is open
|
|
86
|
+
*/
|
|
87
|
+
private checkForHalfOpen;
|
|
88
|
+
/**
|
|
89
|
+
* Transition circuit to OPEN state
|
|
90
|
+
*
|
|
91
|
+
* Rejects all subsequent requests until timeout expires
|
|
92
|
+
*/
|
|
93
|
+
private transitionToOpen;
|
|
94
|
+
/**
|
|
95
|
+
* Transition circuit to HALF_OPEN state
|
|
96
|
+
*
|
|
97
|
+
* Allows test requests to check if service has recovered
|
|
98
|
+
*/
|
|
99
|
+
private transitionToHalfOpen;
|
|
100
|
+
/**
|
|
101
|
+
* Transition circuit to CLOSED state
|
|
102
|
+
*
|
|
103
|
+
* Resumes normal operation after successful recovery
|
|
104
|
+
*/
|
|
105
|
+
private transitionToClosed;
|
|
106
|
+
/**
|
|
107
|
+
* Clean up failure timestamps outside the monitoring period
|
|
108
|
+
*
|
|
109
|
+
* Maintains a sliding window of failures for threshold calculation
|
|
110
|
+
*/
|
|
111
|
+
private cleanupOldFailures;
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=circuit-breaker.provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.provider.d.ts","sourceRoot":"","sources":["../../src/kafka/circuit-breaker.provider.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EACL,oBAAoB,EAEpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAajB;;;;;;;;GAQG;AACH,qBAAa,sBAAsB;IAqB/B,OAAO,CAAC,WAAW;IApBrB,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,KAAK,CAAe;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,eAAe,CAAC,CAAO;IAC/B,OAAO,CAAC,eAAe,CAAO;IAC9B,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,iBAAiB,CAAS;IAElC;;;;;;OAMG;gBAEO,WAAW,EAAE,MAAM,EAC3B,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,EACtC,MAAM,CAAC,EAAE,MAAM;IAcjB;;;;;;OAMG;IACG,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAwBlD;;;;OAIG;IACH,QAAQ,IAAI,mBAAmB;IAY/B;;;;OAIG;IACH,KAAK,IAAI,IAAI;IAmBb;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAarB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAoBrB;;;;OAIG;IACH,OAAO,CAAC,UAAU;IAMlB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAe5B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAiB1B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;CAQ3B"}
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Circuit Breaker Provider
|
|
4
|
+
*
|
|
5
|
+
* Implements the circuit breaker pattern for inter-service Kafka calls.
|
|
6
|
+
* Prevents cascading failures by stopping requests to failing services.
|
|
7
|
+
*
|
|
8
|
+
* State Machine:
|
|
9
|
+
* - CLOSED: Normal operation, requests pass through
|
|
10
|
+
* - OPEN: Service is failing, requests are rejected immediately
|
|
11
|
+
* - HALF_OPEN: Testing if service has recovered, limited requests allowed
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.CircuitBreakerProvider = void 0;
|
|
15
|
+
const types_1 = require("./types");
|
|
16
|
+
const kafka_logger_1 = require("./kafka-logger");
|
|
17
|
+
/**
|
|
18
|
+
* Default circuit breaker configuration
|
|
19
|
+
*/
|
|
20
|
+
const DEFAULT_CIRCUIT_BREAKER_CONFIG = {
|
|
21
|
+
failureThreshold: 5, // Open after 5 failures
|
|
22
|
+
successThreshold: 2, // Close after 2 successes in half-open
|
|
23
|
+
timeout: 60000, // 1 minute before trying half-open
|
|
24
|
+
monitoringPeriod: 120000 // 2 minute window for failure rate
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* CircuitBreakerProvider implements the circuit breaker pattern
|
|
28
|
+
*
|
|
29
|
+
* Features:
|
|
30
|
+
* - Automatic state transitions based on failure/success rates
|
|
31
|
+
* - Configurable thresholds and timeouts
|
|
32
|
+
* - Structured logging of state changes
|
|
33
|
+
* - Statistics tracking for monitoring
|
|
34
|
+
*/
|
|
35
|
+
class CircuitBreakerProvider {
|
|
36
|
+
/**
|
|
37
|
+
* Create a new CircuitBreakerProvider instance
|
|
38
|
+
*
|
|
39
|
+
* @param serviceName - Name of the target service being protected
|
|
40
|
+
* @param config - Optional circuit breaker configuration (uses defaults if not provided)
|
|
41
|
+
* @param logger - Optional NestJS Logger instance
|
|
42
|
+
*/
|
|
43
|
+
constructor(serviceName, config, logger) {
|
|
44
|
+
this.serviceName = serviceName;
|
|
45
|
+
this.config = { ...DEFAULT_CIRCUIT_BREAKER_CONFIG, ...config };
|
|
46
|
+
this.logger = new kafka_logger_1.KafkaLogger(serviceName, logger);
|
|
47
|
+
this.state = types_1.CircuitState.CLOSED;
|
|
48
|
+
this.failures = 0;
|
|
49
|
+
this.successes = 0;
|
|
50
|
+
this.lastStateChange = new Date();
|
|
51
|
+
this.halfOpenAttempts = 0;
|
|
52
|
+
this.totalRequests = 0;
|
|
53
|
+
this.totalFailures = 0;
|
|
54
|
+
this.failureTimestamps = [];
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Execute a function with circuit breaker protection
|
|
58
|
+
*
|
|
59
|
+
* @param fn - Async function to execute
|
|
60
|
+
* @returns Promise resolving to the function result
|
|
61
|
+
* @throws Error if circuit is open or function execution fails
|
|
62
|
+
*/
|
|
63
|
+
async execute(fn) {
|
|
64
|
+
this.totalRequests++;
|
|
65
|
+
// Check circuit state before execution
|
|
66
|
+
if (this.state === types_1.CircuitState.OPEN) {
|
|
67
|
+
this.checkForHalfOpen();
|
|
68
|
+
if (this.state === types_1.CircuitState.OPEN) {
|
|
69
|
+
throw new Error(`Circuit breaker is OPEN for service: ${this.serviceName}. Service is currently unavailable.`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
const result = await fn();
|
|
74
|
+
this.recordSuccess();
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
this.recordFailure();
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get current circuit breaker statistics
|
|
84
|
+
*
|
|
85
|
+
* @returns Circuit breaker statistics object
|
|
86
|
+
*/
|
|
87
|
+
getStats() {
|
|
88
|
+
return {
|
|
89
|
+
state: this.state,
|
|
90
|
+
failures: this.failures,
|
|
91
|
+
successes: this.successes,
|
|
92
|
+
lastFailureTime: this.lastFailureTime,
|
|
93
|
+
lastStateChange: this.lastStateChange,
|
|
94
|
+
totalRequests: this.totalRequests,
|
|
95
|
+
totalFailures: this.totalFailures
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Manually reset circuit breaker to closed state
|
|
100
|
+
*
|
|
101
|
+
* Useful for administrative operations or testing
|
|
102
|
+
*/
|
|
103
|
+
reset() {
|
|
104
|
+
const oldState = this.state;
|
|
105
|
+
this.state = types_1.CircuitState.CLOSED;
|
|
106
|
+
this.failures = 0;
|
|
107
|
+
this.successes = 0;
|
|
108
|
+
this.halfOpenAttempts = 0;
|
|
109
|
+
this.failureTimestamps = [];
|
|
110
|
+
this.lastStateChange = new Date();
|
|
111
|
+
if (oldState !== types_1.CircuitState.CLOSED) {
|
|
112
|
+
this.logger.logCircuitBreakerStateChange(this.serviceName, oldState, types_1.CircuitState.CLOSED, this.getStats());
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Record successful execution
|
|
117
|
+
*
|
|
118
|
+
* Updates success counter and handles state transitions from HALF_OPEN to CLOSED
|
|
119
|
+
*/
|
|
120
|
+
recordSuccess() {
|
|
121
|
+
this.successes++;
|
|
122
|
+
if (this.state === types_1.CircuitState.HALF_OPEN) {
|
|
123
|
+
this.halfOpenAttempts++;
|
|
124
|
+
// Close circuit if success threshold is reached
|
|
125
|
+
if (this.halfOpenAttempts >= this.config.successThreshold) {
|
|
126
|
+
this.transitionToClosed();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Record failed execution
|
|
132
|
+
*
|
|
133
|
+
* Updates failure counter and handles state transitions to OPEN
|
|
134
|
+
*/
|
|
135
|
+
recordFailure() {
|
|
136
|
+
this.failures++;
|
|
137
|
+
this.totalFailures++;
|
|
138
|
+
this.lastFailureTime = new Date();
|
|
139
|
+
this.failureTimestamps.push(this.lastFailureTime);
|
|
140
|
+
// Clean up old failure timestamps outside monitoring period
|
|
141
|
+
this.cleanupOldFailures();
|
|
142
|
+
if (this.state === types_1.CircuitState.HALF_OPEN) {
|
|
143
|
+
// Any failure in half-open state reopens the circuit
|
|
144
|
+
this.transitionToOpen();
|
|
145
|
+
}
|
|
146
|
+
else if (this.state === types_1.CircuitState.CLOSED) {
|
|
147
|
+
// Check if failure threshold is exceeded
|
|
148
|
+
if (this.shouldOpen()) {
|
|
149
|
+
this.transitionToOpen();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Check if circuit should open based on failure threshold
|
|
155
|
+
*
|
|
156
|
+
* @returns True if circuit should open, false otherwise
|
|
157
|
+
*/
|
|
158
|
+
shouldOpen() {
|
|
159
|
+
// Count failures within monitoring period
|
|
160
|
+
const recentFailures = this.failureTimestamps.length;
|
|
161
|
+
return recentFailures >= this.config.failureThreshold;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check if circuit should transition from OPEN to HALF_OPEN
|
|
165
|
+
*
|
|
166
|
+
* Called before each execution when circuit is open
|
|
167
|
+
*/
|
|
168
|
+
checkForHalfOpen() {
|
|
169
|
+
if (this.state !== types_1.CircuitState.OPEN) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const now = new Date();
|
|
173
|
+
const timeSinceStateChange = now.getTime() - this.lastStateChange.getTime();
|
|
174
|
+
if (timeSinceStateChange >= this.config.timeout) {
|
|
175
|
+
this.transitionToHalfOpen();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Transition circuit to OPEN state
|
|
180
|
+
*
|
|
181
|
+
* Rejects all subsequent requests until timeout expires
|
|
182
|
+
*/
|
|
183
|
+
transitionToOpen() {
|
|
184
|
+
const oldState = this.state;
|
|
185
|
+
this.state = types_1.CircuitState.OPEN;
|
|
186
|
+
this.lastStateChange = new Date();
|
|
187
|
+
this.halfOpenAttempts = 0;
|
|
188
|
+
this.logger.logCircuitBreakerStateChange(this.serviceName, oldState, types_1.CircuitState.OPEN, this.getStats());
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Transition circuit to HALF_OPEN state
|
|
192
|
+
*
|
|
193
|
+
* Allows test requests to check if service has recovered
|
|
194
|
+
*/
|
|
195
|
+
transitionToHalfOpen() {
|
|
196
|
+
const oldState = this.state;
|
|
197
|
+
this.state = types_1.CircuitState.HALF_OPEN;
|
|
198
|
+
this.lastStateChange = new Date();
|
|
199
|
+
this.halfOpenAttempts = 0;
|
|
200
|
+
this.successes = 0;
|
|
201
|
+
this.logger.logCircuitBreakerStateChange(this.serviceName, oldState, types_1.CircuitState.HALF_OPEN, this.getStats());
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Transition circuit to CLOSED state
|
|
205
|
+
*
|
|
206
|
+
* Resumes normal operation after successful recovery
|
|
207
|
+
*/
|
|
208
|
+
transitionToClosed() {
|
|
209
|
+
const oldState = this.state;
|
|
210
|
+
this.state = types_1.CircuitState.CLOSED;
|
|
211
|
+
this.lastStateChange = new Date();
|
|
212
|
+
this.failures = 0;
|
|
213
|
+
this.successes = 0;
|
|
214
|
+
this.halfOpenAttempts = 0;
|
|
215
|
+
this.failureTimestamps = [];
|
|
216
|
+
this.logger.logCircuitBreakerStateChange(this.serviceName, oldState, types_1.CircuitState.CLOSED, this.getStats());
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Clean up failure timestamps outside the monitoring period
|
|
220
|
+
*
|
|
221
|
+
* Maintains a sliding window of failures for threshold calculation
|
|
222
|
+
*/
|
|
223
|
+
cleanupOldFailures() {
|
|
224
|
+
const now = new Date();
|
|
225
|
+
const cutoffTime = now.getTime() - this.config.monitoringPeriod;
|
|
226
|
+
this.failureTimestamps = this.failureTimestamps.filter(timestamp => timestamp.getTime() > cutoffTime);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
exports.CircuitBreakerProvider = CircuitBreakerProvider;
|
|
230
|
+
//# sourceMappingURL=circuit-breaker.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"circuit-breaker.provider.js","sourceRoot":"","sources":["../../src/kafka/circuit-breaker.provider.ts"],"names":[],"mappings":"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"}
|