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
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Kafka Logger
|
|
4
|
+
*
|
|
5
|
+
* Provides structured logging for Kafka operations using NestJS Logger.
|
|
6
|
+
* Ensures consistent log formatting and credential filtering across all services.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.KafkaLogger = void 0;
|
|
10
|
+
const common_1 = require("@nestjs/common");
|
|
11
|
+
/**
|
|
12
|
+
* KafkaLogger class provides structured logging for all Kafka-related operations
|
|
13
|
+
*
|
|
14
|
+
* Features:
|
|
15
|
+
* - Uses NestJS Logger for consistent formatting
|
|
16
|
+
* - Filters credentials from logs for security
|
|
17
|
+
* - Provides context-rich log messages
|
|
18
|
+
* - Supports all Kafka lifecycle events
|
|
19
|
+
*/
|
|
20
|
+
class KafkaLogger {
|
|
21
|
+
/**
|
|
22
|
+
* Create a new KafkaLogger instance
|
|
23
|
+
*
|
|
24
|
+
* @param serviceName - Name of the service using this logger
|
|
25
|
+
* @param logger - Optional NestJS Logger instance (creates new one if not provided)
|
|
26
|
+
*/
|
|
27
|
+
constructor(serviceName, logger) {
|
|
28
|
+
this.serviceName = serviceName;
|
|
29
|
+
this.logger = logger || new common_1.Logger('KafkaLogger');
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Log Kafka mode detection
|
|
33
|
+
*
|
|
34
|
+
* @param mode - Detected Kafka mode (local or msk)
|
|
35
|
+
*/
|
|
36
|
+
logModeDetection(mode) {
|
|
37
|
+
this.logger.log(`Kafka mode detected: ${mode.toUpperCase()}`, this.buildContext({ mode }));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Log broker parsing result
|
|
41
|
+
*
|
|
42
|
+
* @param brokers - Array of parsed broker addresses
|
|
43
|
+
*/
|
|
44
|
+
logBrokersParsed(brokers) {
|
|
45
|
+
this.logger.log(`Kafka brokers parsed: ${brokers.join(', ')}`, this.buildContext({ brokerCount: brokers.length, brokers }));
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Log SASL configuration (without credentials)
|
|
49
|
+
*
|
|
50
|
+
* @param mechanism - SASL mechanism being used
|
|
51
|
+
*/
|
|
52
|
+
logSaslConfig(mechanism) {
|
|
53
|
+
this.logger.log(`SASL configuration loaded with mechanism: ${mechanism}`, this.buildContext({ saslMechanism: mechanism }));
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Log connection attempt
|
|
57
|
+
*
|
|
58
|
+
* @param clientId - Kafka client identifier
|
|
59
|
+
*/
|
|
60
|
+
logConnectionAttempt(clientId) {
|
|
61
|
+
this.logger.log(`Attempting to connect Kafka client: ${clientId}`, this.buildContext({ clientId }));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Log successful connection
|
|
65
|
+
*
|
|
66
|
+
* @param clientId - Kafka client identifier
|
|
67
|
+
* @param brokers - Connected broker addresses
|
|
68
|
+
*/
|
|
69
|
+
logConnectionSuccess(clientId, brokers) {
|
|
70
|
+
this.logger.log(`Kafka client connected successfully: ${clientId}`, this.buildContext({ clientId, brokers, brokerCount: brokers.length }));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Log connection failure
|
|
74
|
+
*
|
|
75
|
+
* @param clientId - Kafka client identifier
|
|
76
|
+
* @param error - Error that occurred during connection
|
|
77
|
+
*/
|
|
78
|
+
logConnectionFailure(clientId, error) {
|
|
79
|
+
this.logger.error(`Kafka client connection failed: ${clientId} - ${error.message}`, error.stack, this.buildContext({ clientId, errorMessage: error.message }));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Log subscription registration
|
|
83
|
+
*
|
|
84
|
+
* @param pattern - Message pattern being subscribed to
|
|
85
|
+
* @param clientName - Name of the client subscribing
|
|
86
|
+
*/
|
|
87
|
+
logSubscription(pattern, clientName) {
|
|
88
|
+
this.logger.log(`Subscribed to pattern: ${pattern} on client: ${clientName}`, this.buildContext({ pattern, clientName }));
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Log message send operation
|
|
92
|
+
*
|
|
93
|
+
* @param pattern - Message pattern being sent
|
|
94
|
+
* @param context - Optional additional context
|
|
95
|
+
*/
|
|
96
|
+
logMessageSend(pattern, context) {
|
|
97
|
+
this.logger.log(`Sending message with pattern: ${pattern}`, this.buildContext({ pattern, ...context }));
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Log message receive operation
|
|
101
|
+
*
|
|
102
|
+
* @param pattern - Message pattern received
|
|
103
|
+
* @param context - Optional additional context
|
|
104
|
+
*/
|
|
105
|
+
logMessageReceive(pattern, context) {
|
|
106
|
+
this.logger.log(`Received message with pattern: ${pattern}`, this.buildContext({ pattern, ...context }));
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Log message processing error
|
|
110
|
+
*
|
|
111
|
+
* @param pattern - Message pattern that failed processing
|
|
112
|
+
* @param error - Error that occurred
|
|
113
|
+
* @param context - Optional additional context
|
|
114
|
+
*/
|
|
115
|
+
logProcessingError(pattern, error, context) {
|
|
116
|
+
this.logger.error(`Error processing message with pattern: ${pattern} - ${error.message}`, error.stack, this.buildContext({ pattern, errorMessage: error.message, ...context }));
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Log dead letter queue event
|
|
120
|
+
*
|
|
121
|
+
* @param message - DLQ message being logged
|
|
122
|
+
*/
|
|
123
|
+
logDLQEvent(message) {
|
|
124
|
+
this.logger.warn(`Message sent to DLQ: ${message.originalTopic} - ${message.error.message}`, this.buildContext({
|
|
125
|
+
topic: message.originalTopic,
|
|
126
|
+
partition: message.originalPartition,
|
|
127
|
+
offset: message.originalOffset,
|
|
128
|
+
retryCount: message.retryCount,
|
|
129
|
+
errorMessage: message.error.message,
|
|
130
|
+
errorCode: message.error.code
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Log circuit breaker state change
|
|
135
|
+
*
|
|
136
|
+
* @param serviceName - Target service name
|
|
137
|
+
* @param oldState - Previous circuit state
|
|
138
|
+
* @param newState - New circuit state
|
|
139
|
+
* @param stats - Circuit breaker statistics
|
|
140
|
+
*/
|
|
141
|
+
logCircuitBreakerStateChange(serviceName, oldState, newState, stats) {
|
|
142
|
+
this.logger.warn(`Circuit breaker state changed for ${serviceName}: ${oldState} -> ${newState}`, this.buildContext({
|
|
143
|
+
targetService: serviceName,
|
|
144
|
+
oldState,
|
|
145
|
+
newState,
|
|
146
|
+
failures: stats.failures,
|
|
147
|
+
successes: stats.successes,
|
|
148
|
+
totalRequests: stats.totalRequests,
|
|
149
|
+
totalFailures: stats.totalFailures
|
|
150
|
+
}));
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Build log context with service name and additional metadata
|
|
154
|
+
*
|
|
155
|
+
* @param metadata - Additional metadata to include in context
|
|
156
|
+
* @returns Formatted context string
|
|
157
|
+
*/
|
|
158
|
+
buildContext(metadata) {
|
|
159
|
+
const context = {
|
|
160
|
+
serviceName: this.serviceName,
|
|
161
|
+
...this.filterCredentials(metadata)
|
|
162
|
+
};
|
|
163
|
+
return JSON.stringify(context);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Filter credentials from metadata to prevent logging sensitive information
|
|
167
|
+
*
|
|
168
|
+
* @param metadata - Metadata object that may contain credentials
|
|
169
|
+
* @returns Filtered metadata with credentials removed
|
|
170
|
+
*/
|
|
171
|
+
filterCredentials(metadata) {
|
|
172
|
+
const filtered = { ...metadata };
|
|
173
|
+
// List of keys that should be filtered
|
|
174
|
+
const credentialKeys = [
|
|
175
|
+
'password',
|
|
176
|
+
'saslPassword',
|
|
177
|
+
'sasl_password',
|
|
178
|
+
'kafka_sasl_password',
|
|
179
|
+
'username',
|
|
180
|
+
'saslUsername',
|
|
181
|
+
'sasl_username',
|
|
182
|
+
'kafka_sasl_username',
|
|
183
|
+
'secret',
|
|
184
|
+
'token',
|
|
185
|
+
'apiKey',
|
|
186
|
+
'api_key'
|
|
187
|
+
];
|
|
188
|
+
// Remove credential keys from metadata
|
|
189
|
+
credentialKeys.forEach(key => {
|
|
190
|
+
if (key in filtered) {
|
|
191
|
+
filtered[key] = '[FILTERED]';
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
// Recursively filter nested objects
|
|
195
|
+
Object.keys(filtered).forEach(key => {
|
|
196
|
+
if (filtered[key] && typeof filtered[key] === 'object' && !Array.isArray(filtered[key])) {
|
|
197
|
+
filtered[key] = this.filterCredentials(filtered[key]);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return filtered;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
exports.KafkaLogger = KafkaLogger;
|
|
204
|
+
//# sourceMappingURL=kafka-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kafka-logger.js","sourceRoot":"","sources":["../../src/kafka/kafka-logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kafka Subscription Registry
|
|
3
|
+
*
|
|
4
|
+
* Centralized management of Kafka message pattern subscriptions for microservices.
|
|
5
|
+
* This class provides a structured way to declare and register all Kafka subscriptions
|
|
6
|
+
* in one place instead of scattering them across controllers.
|
|
7
|
+
*
|
|
8
|
+
* Requirements: 3.1, 3.2, 3.3, 3.5
|
|
9
|
+
*/
|
|
10
|
+
import { Logger } from '@nestjs/common';
|
|
11
|
+
import { ClientKafka } from '@nestjs/microservices';
|
|
12
|
+
import { ServiceSubscriptions, SubscriptionConfig } from './types';
|
|
13
|
+
/**
|
|
14
|
+
* KafkaSubscriptionRegistry manages message pattern subscriptions for a service
|
|
15
|
+
*
|
|
16
|
+
* Features:
|
|
17
|
+
* - Centralized subscription declaration
|
|
18
|
+
* - Grouped subscriptions by target service
|
|
19
|
+
* - Ordered registration before client connections
|
|
20
|
+
* - Structured logging of all subscriptions
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const subscriptions: ServiceSubscriptions = {
|
|
25
|
+
* auth: {
|
|
26
|
+
* clientName: 'AUTH_SERVICE',
|
|
27
|
+
* patterns: [AUTH_PATTERNS.UPDATE_USER, AUTH_PATTERNS.GET_USER],
|
|
28
|
+
* description: 'Auth service patterns for user management'
|
|
29
|
+
* }
|
|
30
|
+
* };
|
|
31
|
+
*
|
|
32
|
+
* const registry = new KafkaSubscriptionRegistry(subscriptions);
|
|
33
|
+
* await registry.registerSubscriptions({ authClient });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class KafkaSubscriptionRegistry {
|
|
37
|
+
private logger;
|
|
38
|
+
private subscriptions;
|
|
39
|
+
/**
|
|
40
|
+
* Create a new subscription registry
|
|
41
|
+
*
|
|
42
|
+
* @param subscriptions - Service subscriptions grouped by client
|
|
43
|
+
* @param logger - Optional NestJS logger instance
|
|
44
|
+
*/
|
|
45
|
+
constructor(subscriptions: ServiceSubscriptions, logger?: Logger);
|
|
46
|
+
/**
|
|
47
|
+
* Register all subscriptions for a service
|
|
48
|
+
*
|
|
49
|
+
* This method iterates through all configured subscriptions and registers
|
|
50
|
+
* each pattern with the corresponding Kafka client. Subscriptions are
|
|
51
|
+
* registered in the order they are declared.
|
|
52
|
+
*
|
|
53
|
+
* Requirements: 3.1, 3.3
|
|
54
|
+
*
|
|
55
|
+
* @param clients - Record of ClientKafka instances keyed by client name
|
|
56
|
+
* @returns Promise that resolves when all subscriptions are registered
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* await registry.registerSubscriptions({
|
|
61
|
+
* authClient: authServiceClient,
|
|
62
|
+
* consultationClient: consultationServiceClient
|
|
63
|
+
* });
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
registerSubscriptions(clients: Record<string, ClientKafka>): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Register subscriptions for a specific client
|
|
69
|
+
*
|
|
70
|
+
* This method registers all patterns for a single Kafka client.
|
|
71
|
+
* Each pattern is logged for debugging and traceability.
|
|
72
|
+
*
|
|
73
|
+
* Requirements: 3.2, 3.3, 3.5
|
|
74
|
+
*
|
|
75
|
+
* @param client - ClientKafka instance to register patterns with
|
|
76
|
+
* @param config - Subscription configuration containing patterns and metadata
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* registry.registerClientSubscriptions(authClient, {
|
|
81
|
+
* clientName: 'AUTH_SERVICE',
|
|
82
|
+
* patterns: [AUTH_PATTERNS.UPDATE_USER],
|
|
83
|
+
* description: 'Auth patterns'
|
|
84
|
+
* });
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
registerClientSubscriptions(client: ClientKafka, config: SubscriptionConfig): void;
|
|
88
|
+
/**
|
|
89
|
+
* Get all registered patterns across all clients
|
|
90
|
+
*
|
|
91
|
+
* Requirements: 3.1, 3.2
|
|
92
|
+
*
|
|
93
|
+
* @returns Array of all pattern strings
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```typescript
|
|
97
|
+
* const allPatterns = registry.getAllPatterns();
|
|
98
|
+
* // ['auth.update_user', 'auth.get_user', 'consultation.get_documents']
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
getAllPatterns(): string[];
|
|
102
|
+
/**
|
|
103
|
+
* Get patterns registered for a specific client
|
|
104
|
+
*
|
|
105
|
+
* Requirements: 3.2
|
|
106
|
+
*
|
|
107
|
+
* @param clientName - Name of the client to get patterns for
|
|
108
|
+
* @returns Array of pattern strings for the specified client
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const authPatterns = registry.getPatternsByClient('AUTH_SERVICE');
|
|
113
|
+
* // ['auth.update_user', 'auth.get_user']
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
getPatternsByClient(clientName: string): string[];
|
|
117
|
+
/**
|
|
118
|
+
* Find a client by its configured name
|
|
119
|
+
*
|
|
120
|
+
* This helper method searches through the clients record to find a client
|
|
121
|
+
* that matches the configured client name. It handles various naming conventions
|
|
122
|
+
* (camelCase, lowercase, etc.).
|
|
123
|
+
*
|
|
124
|
+
* @param clients - Record of ClientKafka instances
|
|
125
|
+
* @param clientName - Name to search for
|
|
126
|
+
* @returns ClientKafka instance or undefined if not found
|
|
127
|
+
*
|
|
128
|
+
* @private
|
|
129
|
+
*/
|
|
130
|
+
private findClientByName;
|
|
131
|
+
/**
|
|
132
|
+
* Convert a string to camelCase
|
|
133
|
+
*
|
|
134
|
+
* @param str - String to convert (e.g., "AUTH_SERVICE")
|
|
135
|
+
* @returns camelCase string (e.g., "authService")
|
|
136
|
+
*
|
|
137
|
+
* @private
|
|
138
|
+
*/
|
|
139
|
+
private toCamelCase;
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=subscription-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-registry.d.ts","sourceRoot":"","sources":["../../src/kafka/subscription-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,aAAa,CAAuB;IAE5C;;;;;OAKG;gBACS,aAAa,EAAE,oBAAoB,EAAE,MAAM,CAAC,EAAE,MAAM;IAKhE;;;;;;;;;;;;;;;;;;;OAmBG;IACG,qBAAqB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAgChF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,2BAA2B,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAmClF;;;;;;;;;;;;OAYG;IACH,cAAc,IAAI,MAAM,EAAE;IAY1B;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE;IAUjD;;;;;;;;;;;;OAYG;IACH,OAAO,CAAC,gBAAgB;IA0BxB;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;CAKpB"}
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Kafka Subscription Registry
|
|
4
|
+
*
|
|
5
|
+
* Centralized management of Kafka message pattern subscriptions for microservices.
|
|
6
|
+
* This class provides a structured way to declare and register all Kafka subscriptions
|
|
7
|
+
* in one place instead of scattering them across controllers.
|
|
8
|
+
*
|
|
9
|
+
* Requirements: 3.1, 3.2, 3.3, 3.5
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.KafkaSubscriptionRegistry = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
/**
|
|
15
|
+
* KafkaSubscriptionRegistry manages message pattern subscriptions for a service
|
|
16
|
+
*
|
|
17
|
+
* Features:
|
|
18
|
+
* - Centralized subscription declaration
|
|
19
|
+
* - Grouped subscriptions by target service
|
|
20
|
+
* - Ordered registration before client connections
|
|
21
|
+
* - Structured logging of all subscriptions
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const subscriptions: ServiceSubscriptions = {
|
|
26
|
+
* auth: {
|
|
27
|
+
* clientName: 'AUTH_SERVICE',
|
|
28
|
+
* patterns: [AUTH_PATTERNS.UPDATE_USER, AUTH_PATTERNS.GET_USER],
|
|
29
|
+
* description: 'Auth service patterns for user management'
|
|
30
|
+
* }
|
|
31
|
+
* };
|
|
32
|
+
*
|
|
33
|
+
* const registry = new KafkaSubscriptionRegistry(subscriptions);
|
|
34
|
+
* await registry.registerSubscriptions({ authClient });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
class KafkaSubscriptionRegistry {
|
|
38
|
+
/**
|
|
39
|
+
* Create a new subscription registry
|
|
40
|
+
*
|
|
41
|
+
* @param subscriptions - Service subscriptions grouped by client
|
|
42
|
+
* @param logger - Optional NestJS logger instance
|
|
43
|
+
*/
|
|
44
|
+
constructor(subscriptions, logger) {
|
|
45
|
+
this.subscriptions = subscriptions;
|
|
46
|
+
this.logger = logger || new common_1.Logger(KafkaSubscriptionRegistry.name);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Register all subscriptions for a service
|
|
50
|
+
*
|
|
51
|
+
* This method iterates through all configured subscriptions and registers
|
|
52
|
+
* each pattern with the corresponding Kafka client. Subscriptions are
|
|
53
|
+
* registered in the order they are declared.
|
|
54
|
+
*
|
|
55
|
+
* Requirements: 3.1, 3.3
|
|
56
|
+
*
|
|
57
|
+
* @param clients - Record of ClientKafka instances keyed by client name
|
|
58
|
+
* @returns Promise that resolves when all subscriptions are registered
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* await registry.registerSubscriptions({
|
|
63
|
+
* authClient: authServiceClient,
|
|
64
|
+
* consultationClient: consultationServiceClient
|
|
65
|
+
* });
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
async registerSubscriptions(clients) {
|
|
69
|
+
this.logger.log('Starting subscription registration for all clients');
|
|
70
|
+
// Track total subscriptions registered
|
|
71
|
+
let totalSubscriptions = 0;
|
|
72
|
+
// Iterate through each service subscription configuration
|
|
73
|
+
for (const [serviceName, config] of Object.entries(this.subscriptions)) {
|
|
74
|
+
if (!config) {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
// Find the matching client by name
|
|
78
|
+
const client = this.findClientByName(clients, config.clientName);
|
|
79
|
+
if (!client) {
|
|
80
|
+
this.logger.warn(`Client not found for service "${serviceName}" (expected client name: "${config.clientName}"). Skipping subscriptions.`);
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Register subscriptions for this client
|
|
84
|
+
this.registerClientSubscriptions(client, config);
|
|
85
|
+
totalSubscriptions += config.patterns.length;
|
|
86
|
+
}
|
|
87
|
+
this.logger.log(`Subscription registration complete. Total patterns registered: ${totalSubscriptions}`);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Register subscriptions for a specific client
|
|
91
|
+
*
|
|
92
|
+
* This method registers all patterns for a single Kafka client.
|
|
93
|
+
* Each pattern is logged for debugging and traceability.
|
|
94
|
+
*
|
|
95
|
+
* Requirements: 3.2, 3.3, 3.5
|
|
96
|
+
*
|
|
97
|
+
* @param client - ClientKafka instance to register patterns with
|
|
98
|
+
* @param config - Subscription configuration containing patterns and metadata
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* ```typescript
|
|
102
|
+
* registry.registerClientSubscriptions(authClient, {
|
|
103
|
+
* clientName: 'AUTH_SERVICE',
|
|
104
|
+
* patterns: [AUTH_PATTERNS.UPDATE_USER],
|
|
105
|
+
* description: 'Auth patterns'
|
|
106
|
+
* });
|
|
107
|
+
* ```
|
|
108
|
+
*/
|
|
109
|
+
registerClientSubscriptions(client, config) {
|
|
110
|
+
const { clientName, patterns, description } = config;
|
|
111
|
+
this.logger.log(`Registering ${patterns.length} subscription(s) for client "${clientName}"${description ? `: ${description}` : ''}`);
|
|
112
|
+
// Register each pattern in order
|
|
113
|
+
for (const pattern of patterns) {
|
|
114
|
+
try {
|
|
115
|
+
// Subscribe to response pattern
|
|
116
|
+
client.subscribeToResponseOf(pattern);
|
|
117
|
+
this.logger.debug(`Subscribed to pattern "${pattern}" on client "${clientName}"`);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
121
|
+
const errorStack = error instanceof Error ? error.stack : undefined;
|
|
122
|
+
this.logger.error(`Failed to subscribe to pattern "${pattern}" on client "${clientName}": ${errorMessage}`, errorStack);
|
|
123
|
+
throw error;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
this.logger.log(`Successfully registered ${patterns.length} pattern(s) for client "${clientName}"`);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Get all registered patterns across all clients
|
|
130
|
+
*
|
|
131
|
+
* Requirements: 3.1, 3.2
|
|
132
|
+
*
|
|
133
|
+
* @returns Array of all pattern strings
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const allPatterns = registry.getAllPatterns();
|
|
138
|
+
* // ['auth.update_user', 'auth.get_user', 'consultation.get_documents']
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
getAllPatterns() {
|
|
142
|
+
const patterns = [];
|
|
143
|
+
for (const config of Object.values(this.subscriptions)) {
|
|
144
|
+
if (config && config.patterns) {
|
|
145
|
+
patterns.push(...config.patterns);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return patterns;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Get patterns registered for a specific client
|
|
152
|
+
*
|
|
153
|
+
* Requirements: 3.2
|
|
154
|
+
*
|
|
155
|
+
* @param clientName - Name of the client to get patterns for
|
|
156
|
+
* @returns Array of pattern strings for the specified client
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const authPatterns = registry.getPatternsByClient('AUTH_SERVICE');
|
|
161
|
+
* // ['auth.update_user', 'auth.get_user']
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
getPatternsByClient(clientName) {
|
|
165
|
+
for (const config of Object.values(this.subscriptions)) {
|
|
166
|
+
if (config && config.clientName === clientName) {
|
|
167
|
+
return [...config.patterns];
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return [];
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Find a client by its configured name
|
|
174
|
+
*
|
|
175
|
+
* This helper method searches through the clients record to find a client
|
|
176
|
+
* that matches the configured client name. It handles various naming conventions
|
|
177
|
+
* (camelCase, lowercase, etc.).
|
|
178
|
+
*
|
|
179
|
+
* @param clients - Record of ClientKafka instances
|
|
180
|
+
* @param clientName - Name to search for
|
|
181
|
+
* @returns ClientKafka instance or undefined if not found
|
|
182
|
+
*
|
|
183
|
+
* @private
|
|
184
|
+
*/
|
|
185
|
+
findClientByName(clients, clientName) {
|
|
186
|
+
// Try exact match first
|
|
187
|
+
if (clients[clientName]) {
|
|
188
|
+
return clients[clientName];
|
|
189
|
+
}
|
|
190
|
+
// Try case-insensitive match
|
|
191
|
+
const normalizedName = clientName.toLowerCase();
|
|
192
|
+
for (const [key, client] of Object.entries(clients)) {
|
|
193
|
+
if (key.toLowerCase() === normalizedName) {
|
|
194
|
+
return client;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// Try converting to camelCase (e.g., AUTH_SERVICE -> authService)
|
|
198
|
+
const camelCaseName = this.toCamelCase(clientName);
|
|
199
|
+
if (clients[camelCaseName]) {
|
|
200
|
+
return clients[camelCaseName];
|
|
201
|
+
}
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Convert a string to camelCase
|
|
206
|
+
*
|
|
207
|
+
* @param str - String to convert (e.g., "AUTH_SERVICE")
|
|
208
|
+
* @returns camelCase string (e.g., "authService")
|
|
209
|
+
*
|
|
210
|
+
* @private
|
|
211
|
+
*/
|
|
212
|
+
toCamelCase(str) {
|
|
213
|
+
return str
|
|
214
|
+
.toLowerCase()
|
|
215
|
+
.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
exports.KafkaSubscriptionRegistry = KafkaSubscriptionRegistry;
|
|
219
|
+
//# sourceMappingURL=subscription-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-registry.js","sourceRoot":"","sources":["../../src/kafka/subscription-registry.ts"],"names":[],"mappings":"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"}
|