@opra/kafka 1.27.4 → 1.28.1
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/index.d.ts +0 -1
- package/index.js +0 -1
- package/kafka-adapter.d.ts +27 -41
- package/kafka-adapter.js +82 -129
- package/kafka-context.d.ts +3 -7
- package/kafka-context.js +0 -4
- package/package.json +5 -5
- package/parse-regexp.d.ts +1 -0
- package/parse-regexp.js +8 -0
- package/parsers/binary.parser.d.ts +0 -8
- package/parsers/binary.parser.js +0 -9
- package/parsers/string.parser.d.ts +0 -8
- package/parsers/string.parser.js +0 -9
- package/request-parser.d.ts +0 -11
- package/request-parser.js +0 -11
package/index.d.ts
CHANGED
package/index.js
CHANGED
package/kafka-adapter.d.ts
CHANGED
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { ApiDocument, MQApi, MQController, MQOperation, OpraException, OpraSchema } from '@opra/common';
|
|
2
|
-
import {
|
|
3
|
-
import { type
|
|
2
|
+
import { PlatformAdapter } from '@opra/core';
|
|
3
|
+
import { type BaseOptions, type ConsumeOptions, Consumer, type ConsumerOptions as _ConsumerOptions, type Message as _Message, type MessagesStream } from '@platformatic/kafka';
|
|
4
4
|
import type { StrictOmit } from 'ts-gems';
|
|
5
5
|
import { KafkaContext } from './kafka-context.js';
|
|
6
|
-
export
|
|
7
|
-
consumer:
|
|
6
|
+
export type OperationArguments = {
|
|
7
|
+
consumer: KafkaAdapter.ConsumerOptions;
|
|
8
8
|
selfConsumer?: boolean;
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
} & Required<{
|
|
10
|
+
subscribe: KafkaAdapter.OperationOptions['subscribe'];
|
|
11
|
+
}>;
|
|
11
12
|
interface HandlerArguments {
|
|
12
13
|
consumer: Consumer;
|
|
13
14
|
controller: MQController;
|
|
14
15
|
instance: any;
|
|
15
16
|
operation: MQOperation;
|
|
16
|
-
operationConfig:
|
|
17
|
-
handler:
|
|
17
|
+
operationConfig: OperationArguments;
|
|
18
|
+
handler: KafkaAdapter.MessageHandler;
|
|
19
|
+
stream?: MessagesStream<any, any, any, any>;
|
|
18
20
|
topics: (string | RegExp)[];
|
|
19
21
|
}
|
|
20
22
|
/**
|
|
@@ -26,9 +28,8 @@ export declare class KafkaAdapter extends PlatformAdapter<KafkaAdapter.Events> {
|
|
|
26
28
|
static readonly PlatformName = "kafka";
|
|
27
29
|
protected _config: KafkaAdapter.Config;
|
|
28
30
|
protected _controllerInstances: Map<MQController, any>;
|
|
29
|
-
protected _consumers: Map<string, Consumer
|
|
31
|
+
protected _consumers: Map<string, Consumer<any, any, any, any>>;
|
|
30
32
|
protected _handlerArgs: HandlerArguments[];
|
|
31
|
-
protected _kafka: Kafka;
|
|
32
33
|
protected _status: KafkaAdapter.Status;
|
|
33
34
|
readonly transform: OpraSchema.Transport;
|
|
34
35
|
readonly platform = "kafka";
|
|
@@ -45,10 +46,6 @@ export declare class KafkaAdapter extends PlatformAdapter<KafkaAdapter.Events> {
|
|
|
45
46
|
* Gets the MQ API defined in the document.
|
|
46
47
|
*/
|
|
47
48
|
get api(): MQApi;
|
|
48
|
-
/**
|
|
49
|
-
* Gets the Kafka client instance.
|
|
50
|
-
*/
|
|
51
|
-
get kafka(): Kafka;
|
|
52
49
|
/**
|
|
53
50
|
* Gets the configuration scope for the adapter.
|
|
54
51
|
*/
|
|
@@ -72,7 +69,7 @@ export declare class KafkaAdapter extends PlatformAdapter<KafkaAdapter.Events> {
|
|
|
72
69
|
* Closes all active Kafka consumers and clears internal caches.
|
|
73
70
|
* This effectively stops the service and returns it to the idle state.
|
|
74
71
|
*/
|
|
75
|
-
close(): Promise<void>;
|
|
72
|
+
close(force?: boolean): Promise<void>;
|
|
76
73
|
/**
|
|
77
74
|
* Retrieves a controller instance by its path.
|
|
78
75
|
*
|
|
@@ -86,10 +83,11 @@ export declare class KafkaAdapter extends PlatformAdapter<KafkaAdapter.Events> {
|
|
|
86
83
|
* @param controller - The MQ controller containing the operation.
|
|
87
84
|
* @param instance - The actual instance of the controller class.
|
|
88
85
|
* @param operation - The MQ operation being configured.
|
|
86
|
+
* @param availableTopics - List of available topics (Retrieved from Kafka admin client).
|
|
89
87
|
* @returns A promise that resolves to the operation configuration or undefined if not applicable.
|
|
90
88
|
* @protected
|
|
91
89
|
*/
|
|
92
|
-
protected
|
|
90
|
+
protected _getOperationArguments(controller: MQController, instance: any, operation: MQOperation, availableTopics: string[]): Promise<OperationArguments | undefined>;
|
|
93
91
|
/**
|
|
94
92
|
* Creates and prepares all consumers defined in the API document.
|
|
95
93
|
* @protected
|
|
@@ -127,19 +125,6 @@ export declare class KafkaAdapter extends PlatformAdapter<KafkaAdapter.Events> {
|
|
|
127
125
|
* @protected
|
|
128
126
|
*/
|
|
129
127
|
protected _wrapExceptions(exceptions: any[]): OpraException[];
|
|
130
|
-
/**
|
|
131
|
-
* Creates a KafkaJS log creator that redirects logs to the provided logger.
|
|
132
|
-
*
|
|
133
|
-
* @param logger - The logger instance to use.
|
|
134
|
-
* @param logExtra - Whether to include additional metadata in the logs.
|
|
135
|
-
* @returns A log creator function for KafkaJS.
|
|
136
|
-
* @protected
|
|
137
|
-
*/
|
|
138
|
-
protected _createLogCreator(logger: ILogger, logExtra?: boolean): ({ namespace, level, log }: {
|
|
139
|
-
namespace: any;
|
|
140
|
-
level: any;
|
|
141
|
-
log: any;
|
|
142
|
-
}) => any;
|
|
143
128
|
}
|
|
144
129
|
/**
|
|
145
130
|
* Namespace for KafkaAdapter related types and interfaces.
|
|
@@ -152,18 +137,21 @@ export declare namespace KafkaAdapter {
|
|
|
152
137
|
/**
|
|
153
138
|
* Represents the operational status of the Kafka adapter.
|
|
154
139
|
*/
|
|
155
|
-
type Status = 'idle' | 'starting' | 'started';
|
|
140
|
+
type Status = 'idle' | 'starting' | 'started' | 'closing';
|
|
141
|
+
type ClientOptions = BaseOptions;
|
|
142
|
+
type ConsumerOptions = _ConsumerOptions<any, any, any, any>;
|
|
143
|
+
type SubscribeOptions = ConsumeOptions<any, any, any, any>;
|
|
144
|
+
type Message = _Message<any, any, any, any>;
|
|
145
|
+
type MessageHandler = (message: Message) => Promise<void>;
|
|
156
146
|
/**
|
|
157
147
|
* Configuration options for the Kafka adapter.
|
|
158
148
|
*/
|
|
159
149
|
interface Config extends PlatformAdapter.Options {
|
|
160
|
-
client:
|
|
161
|
-
consumers?: Record<string, StrictOmit<
|
|
150
|
+
client: ClientOptions;
|
|
151
|
+
consumers?: Record<string, StrictOmit<ConsumerOptions, 'groupId' | keyof ClientOptions>>;
|
|
162
152
|
defaults?: {
|
|
163
|
-
consumer?:
|
|
164
|
-
subscribe?:
|
|
165
|
-
fromBeginning?: boolean;
|
|
166
|
-
};
|
|
153
|
+
consumer?: ConsumerOptions;
|
|
154
|
+
subscribe?: SubscribeOptions;
|
|
167
155
|
};
|
|
168
156
|
scope?: string;
|
|
169
157
|
interceptors?: (InterceptorFunction | IKafkaInterceptor)[];
|
|
@@ -176,13 +164,11 @@ export declare namespace KafkaAdapter {
|
|
|
176
164
|
/**
|
|
177
165
|
* Group ID or consumer configuration.
|
|
178
166
|
*/
|
|
179
|
-
consumer?: string |
|
|
167
|
+
consumer?: string | ConsumerOptions;
|
|
180
168
|
/**
|
|
181
169
|
* Subscription options for the topic.
|
|
182
170
|
*/
|
|
183
|
-
subscribe?:
|
|
184
|
-
fromBeginning?: boolean;
|
|
185
|
-
};
|
|
171
|
+
subscribe?: SubscribeOptions;
|
|
186
172
|
}
|
|
187
173
|
/**
|
|
188
174
|
* Type definition for a Kafka interceptor function.
|
|
@@ -208,7 +194,7 @@ export declare namespace KafkaAdapter {
|
|
|
208
194
|
error: [error: Error, context: KafkaContext | undefined];
|
|
209
195
|
finish: [context: KafkaContext, result: any];
|
|
210
196
|
execute: [context: KafkaContext];
|
|
211
|
-
message: [
|
|
197
|
+
message: [message: Message];
|
|
212
198
|
}
|
|
213
199
|
}
|
|
214
200
|
export {};
|
package/kafka-adapter.js
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import { ApiDocument, MQ_CONTROLLER_METADATA, MQApi, MQController, MQOperation, OpraException, OpraSchema, } from '@opra/common';
|
|
2
2
|
import { kAssetCache, PlatformAdapter } from '@opra/core';
|
|
3
|
-
import {
|
|
3
|
+
import { Admin, Consumer, stringDeserializers, } from '@platformatic/kafka';
|
|
4
4
|
import { vg } from 'valgen';
|
|
5
5
|
import { KAFKA_DEFAULT_GROUP, KAFKA_OPERATION_METADATA, KAFKA_OPERATION_METADATA_RESOLVER, } from './constants.js';
|
|
6
6
|
import { KafkaContext } from './kafka-context.js';
|
|
7
|
-
import {
|
|
7
|
+
import { parseRegExp } from './parse-regexp.js';
|
|
8
8
|
const globalErrorTypes = ['unhandledRejection', 'uncaughtException'];
|
|
9
|
-
const signalTraps = ['SIGTERM', 'SIGINT', 'SIGUSR2'];
|
|
10
|
-
const kGroupId = Symbol('kGroupId');
|
|
11
9
|
const noOp = () => undefined;
|
|
12
10
|
/**
|
|
13
11
|
* Adapter for integrating Kafka into the Opra platform.
|
|
@@ -20,6 +18,7 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
20
18
|
_controllerInstances = new Map();
|
|
21
19
|
_consumers = new Map();
|
|
22
20
|
_handlerArgs = [];
|
|
21
|
+
// declare protected _kafka: Kafka;
|
|
23
22
|
_status = 'idle';
|
|
24
23
|
transform = 'mq';
|
|
25
24
|
platform = KafkaAdapter.PlatformName;
|
|
@@ -47,9 +46,6 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
47
46
|
return this.close();
|
|
48
47
|
});
|
|
49
48
|
});
|
|
50
|
-
signalTraps.forEach(type => {
|
|
51
|
-
process.once(type, () => this.close());
|
|
52
|
-
});
|
|
53
49
|
}
|
|
54
50
|
/**
|
|
55
51
|
* Gets the MQ API defined in the document.
|
|
@@ -57,12 +53,13 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
57
53
|
get api() {
|
|
58
54
|
return this.document.getMqApi();
|
|
59
55
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
56
|
+
//
|
|
57
|
+
// /**
|
|
58
|
+
// * Gets the Kafka client instance.
|
|
59
|
+
// */
|
|
60
|
+
// get kafka(): Kafka {
|
|
61
|
+
// return this._kafka;
|
|
62
|
+
// }
|
|
66
63
|
/**
|
|
67
64
|
* Gets the configuration scope for the adapter.
|
|
68
65
|
*/
|
|
@@ -80,14 +77,8 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
80
77
|
* This method is called automatically by {@link start} if not already initialized.
|
|
81
78
|
*/
|
|
82
79
|
async initialize() {
|
|
83
|
-
if (this.
|
|
80
|
+
if (this._consumers.size)
|
|
84
81
|
return;
|
|
85
|
-
this._kafka = new Kafka({
|
|
86
|
-
...this._config.client,
|
|
87
|
-
logCreator: this.logger
|
|
88
|
-
? () => this._createLogCreator(this.logger, this._config.logExtra)
|
|
89
|
-
: undefined,
|
|
90
|
-
});
|
|
91
82
|
await this._createAllConsumers();
|
|
92
83
|
}
|
|
93
84
|
/**
|
|
@@ -101,66 +92,37 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
101
92
|
await this.initialize();
|
|
102
93
|
this._status = 'starting';
|
|
103
94
|
try {
|
|
104
|
-
/* Connect all consumers */
|
|
105
|
-
for (const consumer of this._consumers.values()) {
|
|
106
|
-
await consumer.connect().catch(e => {
|
|
107
|
-
this._emitError(e);
|
|
108
|
-
throw e;
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
95
|
/* Subscribe to channels */
|
|
112
96
|
for (const args of this._handlerArgs) {
|
|
113
|
-
const { consumer,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
throw e;
|
|
125
|
-
});
|
|
126
|
-
this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
|
|
127
|
-
}
|
|
128
|
-
/* Start consumer listeners */
|
|
129
|
-
const topicMap = new Map();
|
|
130
|
-
for (const consumer of this._consumers.values()) {
|
|
131
|
-
const groupId = consumer[kGroupId];
|
|
132
|
-
await consumer
|
|
133
|
-
.run({
|
|
134
|
-
eachMessage: async (payload) => {
|
|
135
|
-
await this.emitAsync('message', payload).catch(() => undefined);
|
|
136
|
-
const { topic } = payload;
|
|
137
|
-
const topicCacheKey = groupId + ':' + topic;
|
|
97
|
+
const { consumer, operationConfig } = args;
|
|
98
|
+
if (!operationConfig.subscribe?.topics?.length)
|
|
99
|
+
continue;
|
|
100
|
+
args.stream = await consumer.consume(operationConfig.subscribe);
|
|
101
|
+
const topicMap = new Map();
|
|
102
|
+
args.stream.on('data', message => {
|
|
103
|
+
this.emitSafe('message', message);
|
|
104
|
+
Promise.resolve()
|
|
105
|
+
.then(async () => {
|
|
106
|
+
const { topic } = message;
|
|
107
|
+
const topicCacheKey = consumer.groupId + ':' + topic;
|
|
138
108
|
let handlerArgsArray = topicMap.get(topicCacheKey);
|
|
139
109
|
if (!handlerArgsArray) {
|
|
140
|
-
handlerArgsArray = this._handlerArgs.filter(
|
|
141
|
-
|
|
110
|
+
handlerArgsArray = this._handlerArgs.filter(hargs => hargs.consumer === consumer &&
|
|
111
|
+
hargs.operationConfig.subscribe?.topics.includes(topic));
|
|
142
112
|
/* istanbul ignore next */
|
|
143
113
|
if (!handlerArgsArray) {
|
|
144
|
-
|
|
145
|
-
return;
|
|
114
|
+
throw new Error(`Unhandled topic (${topic})`);
|
|
146
115
|
}
|
|
147
116
|
topicMap.set(topicCacheKey, handlerArgsArray);
|
|
148
117
|
}
|
|
149
118
|
/* Iterate and call all matching handlers */
|
|
150
|
-
for (const
|
|
151
|
-
|
|
152
|
-
await args.handler(payload);
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
this._emitError(e);
|
|
156
|
-
}
|
|
119
|
+
for (const hargs of handlerArgsArray) {
|
|
120
|
+
await hargs.handler(message);
|
|
157
121
|
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
.catch(e => {
|
|
161
|
-
this._emitError(e);
|
|
162
|
-
throw e;
|
|
122
|
+
})
|
|
123
|
+
.catch(e => this._emitError(e));
|
|
163
124
|
});
|
|
125
|
+
this.logger?.info?.(`Subscribed to topic${args.topics.length > 1 ? 's' : ''} "${args.topics}"`);
|
|
164
126
|
}
|
|
165
127
|
this._status = 'started';
|
|
166
128
|
}
|
|
@@ -173,8 +135,9 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
173
135
|
* Closes all active Kafka consumers and clears internal caches.
|
|
174
136
|
* This effectively stops the service and returns it to the idle state.
|
|
175
137
|
*/
|
|
176
|
-
async close() {
|
|
177
|
-
|
|
138
|
+
async close(force) {
|
|
139
|
+
this._status = 'closing';
|
|
140
|
+
await Promise.allSettled(Array.from(this._consumers.values()).map(c => c.close(force)));
|
|
178
141
|
this._consumers.clear();
|
|
179
142
|
this._controllerInstances.clear();
|
|
180
143
|
this._status = 'idle';
|
|
@@ -195,10 +158,11 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
195
158
|
* @param controller - The MQ controller containing the operation.
|
|
196
159
|
* @param instance - The actual instance of the controller class.
|
|
197
160
|
* @param operation - The MQ operation being configured.
|
|
161
|
+
* @param availableTopics - List of available topics (Retrieved from Kafka admin client).
|
|
198
162
|
* @returns A promise that resolves to the operation configuration or undefined if not applicable.
|
|
199
163
|
* @protected
|
|
200
164
|
*/
|
|
201
|
-
async
|
|
165
|
+
async _getOperationArguments(controller, instance, operation, availableTopics) {
|
|
202
166
|
if (typeof instance[operation.name] !== 'function')
|
|
203
167
|
return;
|
|
204
168
|
const proto = controller.ctor?.prototype || Object.getPrototypeOf(instance);
|
|
@@ -206,9 +170,11 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
206
170
|
return;
|
|
207
171
|
const operationConfig = {
|
|
208
172
|
consumer: {
|
|
173
|
+
clientId: '',
|
|
209
174
|
groupId: KAFKA_DEFAULT_GROUP,
|
|
175
|
+
bootstrapBrokers: [],
|
|
210
176
|
},
|
|
211
|
-
subscribe: {},
|
|
177
|
+
subscribe: { topics: [] },
|
|
212
178
|
};
|
|
213
179
|
if (this._config.defaults) {
|
|
214
180
|
if (this._config.defaults.subscribe) {
|
|
@@ -243,6 +209,29 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
243
209
|
}
|
|
244
210
|
}
|
|
245
211
|
}
|
|
212
|
+
Object.assign(operationConfig.consumer, this._config.client);
|
|
213
|
+
const selectedTopics = [];
|
|
214
|
+
const topics = Array.isArray(operation.channel)
|
|
215
|
+
? operation.channel
|
|
216
|
+
: [operation.channel];
|
|
217
|
+
for (let topic of topics) {
|
|
218
|
+
if (!topic)
|
|
219
|
+
continue;
|
|
220
|
+
if (typeof topic === 'string' && topic.startsWith('/'))
|
|
221
|
+
topic = parseRegExp(topic);
|
|
222
|
+
else if (typeof topic === 'string' && topic.startsWith('^'))
|
|
223
|
+
topic = parseRegExp('/' + topic + '/');
|
|
224
|
+
if (topic instanceof RegExp) {
|
|
225
|
+
const matchedTopics = availableTopics
|
|
226
|
+
.filter(t => (topic.test(t) ? t : undefined))
|
|
227
|
+
.filter(t => !!t);
|
|
228
|
+
selectedTopics.push(...matchedTopics);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
selectedTopics.push(String(topic));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
operationConfig.subscribe.topics = selectedTopics;
|
|
246
235
|
return operationConfig;
|
|
247
236
|
}
|
|
248
237
|
/**
|
|
@@ -250,6 +239,13 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
250
239
|
* @protected
|
|
251
240
|
*/
|
|
252
241
|
async _createAllConsumers() {
|
|
242
|
+
const admin = new Admin({
|
|
243
|
+
...this._config.client,
|
|
244
|
+
});
|
|
245
|
+
const availableTopics = await admin.listTopics({
|
|
246
|
+
includeInternals: false,
|
|
247
|
+
});
|
|
248
|
+
await admin.close();
|
|
253
249
|
for (const controller of this.document.getMqApi().controllers.values()) {
|
|
254
250
|
let instance = controller.instance;
|
|
255
251
|
if (!instance && controller.ctor)
|
|
@@ -259,7 +255,7 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
259
255
|
this._controllerInstances.set(controller, instance);
|
|
260
256
|
/* Build HandlerData array */
|
|
261
257
|
for (const operation of controller.operations.values()) {
|
|
262
|
-
const operationConfig = await this.
|
|
258
|
+
const operationConfig = await this._getOperationArguments(controller, instance, operation, availableTopics);
|
|
263
259
|
if (!operationConfig)
|
|
264
260
|
continue;
|
|
265
261
|
const args = {
|
|
@@ -295,8 +291,11 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
295
291
|
}
|
|
296
292
|
/* Create consumers */
|
|
297
293
|
if (!consumer) {
|
|
298
|
-
consumer =
|
|
299
|
-
|
|
294
|
+
consumer = new Consumer({
|
|
295
|
+
...operationConfig.consumer,
|
|
296
|
+
deserializers: stringDeserializers,
|
|
297
|
+
});
|
|
298
|
+
// consumer[kGroupId] = operationConfig.consumer.groupId;
|
|
300
299
|
this._consumers.set(operationConfig.consumer.groupId, consumer);
|
|
301
300
|
}
|
|
302
301
|
args.consumer = consumer;
|
|
@@ -311,8 +310,6 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
311
310
|
_createHandler(args) {
|
|
312
311
|
const { controller, instance, operation } = args;
|
|
313
312
|
/* Prepare parsers */
|
|
314
|
-
const parseKey = RequestParser.STRING;
|
|
315
|
-
const parsePayload = RequestParser.STRING;
|
|
316
313
|
/* Prepare decoders */
|
|
317
314
|
const decodeKey = operation.generateKeyCodec('decode', {
|
|
318
315
|
scope: this.scope,
|
|
@@ -332,7 +329,7 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
332
329
|
this[kAssetCache].set(header, 'decode', decode);
|
|
333
330
|
}
|
|
334
331
|
});
|
|
335
|
-
args.handler = async (
|
|
332
|
+
args.handler = async (message) => {
|
|
336
333
|
const operationHandler = instance[operation.name];
|
|
337
334
|
let key;
|
|
338
335
|
let payload;
|
|
@@ -340,20 +337,18 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
340
337
|
try {
|
|
341
338
|
/* Parse and decode `key` */
|
|
342
339
|
if (message.key) {
|
|
343
|
-
|
|
344
|
-
key = decodeKey(s);
|
|
340
|
+
key = decodeKey(message.key);
|
|
345
341
|
}
|
|
346
342
|
/* Parse and decode `payload` */
|
|
347
343
|
if (message.value != null) {
|
|
348
|
-
|
|
349
|
-
payload = decodePayload(s);
|
|
344
|
+
payload = decodePayload(message.value);
|
|
350
345
|
}
|
|
351
346
|
/* Parse and decode `headers` */
|
|
352
347
|
if (message.headers) {
|
|
353
|
-
for (const [k, v] of
|
|
348
|
+
for (const [k, v] of message.headers.entries()) {
|
|
354
349
|
const header = operation.findHeader(k);
|
|
355
350
|
const decode = this[kAssetCache].get(header, 'decode') || vg.isAny();
|
|
356
|
-
headers[k] = decode(
|
|
351
|
+
headers[k] = decode(v);
|
|
357
352
|
}
|
|
358
353
|
}
|
|
359
354
|
}
|
|
@@ -368,14 +363,13 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
368
363
|
__controller: instance,
|
|
369
364
|
__oprDef: operation,
|
|
370
365
|
__handler: operationHandler,
|
|
371
|
-
topic,
|
|
372
|
-
partition,
|
|
366
|
+
topic: message.topic,
|
|
367
|
+
partition: message.partition,
|
|
373
368
|
payload,
|
|
374
369
|
key,
|
|
375
370
|
headers,
|
|
376
371
|
rawMessage: message,
|
|
377
|
-
|
|
378
|
-
pause,
|
|
372
|
+
commit: () => message.commit(),
|
|
379
373
|
});
|
|
380
374
|
await this.emitAsync('execute', context);
|
|
381
375
|
try {
|
|
@@ -432,45 +426,4 @@ export class KafkaAdapter extends PlatformAdapter {
|
|
|
432
426
|
wrappedErrors.push(new OpraException('Internal Server Error'));
|
|
433
427
|
return wrappedErrors;
|
|
434
428
|
}
|
|
435
|
-
/**
|
|
436
|
-
* Creates a KafkaJS log creator that redirects logs to the provided logger.
|
|
437
|
-
*
|
|
438
|
-
* @param logger - The logger instance to use.
|
|
439
|
-
* @param logExtra - Whether to include additional metadata in the logs.
|
|
440
|
-
* @returns A log creator function for KafkaJS.
|
|
441
|
-
* @protected
|
|
442
|
-
*/
|
|
443
|
-
_createLogCreator(logger, logExtra) {
|
|
444
|
-
return ({ namespace, level, log }) => {
|
|
445
|
-
const { message, error, ...extra } = log;
|
|
446
|
-
delete extra.namespace;
|
|
447
|
-
delete extra.timestamp;
|
|
448
|
-
delete extra.logger;
|
|
449
|
-
let fn;
|
|
450
|
-
switch (level) {
|
|
451
|
-
case logLevel.ERROR:
|
|
452
|
-
fn = logger.error || logger.info;
|
|
453
|
-
break;
|
|
454
|
-
case logLevel.WARN:
|
|
455
|
-
fn = logger.warn || logger.info;
|
|
456
|
-
break;
|
|
457
|
-
case logLevel.DEBUG:
|
|
458
|
-
fn = logger.debug;
|
|
459
|
-
break;
|
|
460
|
-
case logLevel.NOTHING:
|
|
461
|
-
break;
|
|
462
|
-
default:
|
|
463
|
-
fn = logger.info;
|
|
464
|
-
break;
|
|
465
|
-
}
|
|
466
|
-
if (!fn)
|
|
467
|
-
return;
|
|
468
|
-
if (!logExtra)
|
|
469
|
-
return fn.call(logger, error || message);
|
|
470
|
-
return fn.call(logger, error || message, {
|
|
471
|
-
...extra,
|
|
472
|
-
namespace,
|
|
473
|
-
});
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
429
|
}
|
package/kafka-context.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { MQController, MQOperation } from '@opra/common';
|
|
2
2
|
import { ExecutionContext } from '@opra/core';
|
|
3
|
-
import type { KafkaMessage } from 'kafkajs';
|
|
4
3
|
import type { AsyncEventEmitter } from 'node-events-async';
|
|
5
4
|
import type { KafkaAdapter } from './kafka-adapter.js';
|
|
6
5
|
/**
|
|
@@ -18,9 +17,7 @@ export declare class KafkaContext extends ExecutionContext implements AsyncEvent
|
|
|
18
17
|
readonly payload: any;
|
|
19
18
|
readonly partition: number;
|
|
20
19
|
readonly headers: Record<string, any>;
|
|
21
|
-
readonly rawMessage:
|
|
22
|
-
readonly heartbeat: () => Promise<void>;
|
|
23
|
-
readonly pause: () => void;
|
|
20
|
+
readonly rawMessage: KafkaAdapter.Message;
|
|
24
21
|
/**
|
|
25
22
|
* Initializes a new instance of the KafkaContext.
|
|
26
23
|
*
|
|
@@ -40,8 +37,7 @@ export declare namespace KafkaContext {
|
|
|
40
37
|
key: any;
|
|
41
38
|
payload: any;
|
|
42
39
|
headers: Record<string, any>;
|
|
43
|
-
rawMessage:
|
|
44
|
-
|
|
45
|
-
pause(): void;
|
|
40
|
+
rawMessage: KafkaAdapter.Message;
|
|
41
|
+
commit(): void | Promise<void>;
|
|
46
42
|
}
|
|
47
43
|
}
|
package/kafka-context.js
CHANGED
|
@@ -11,8 +11,6 @@ export class KafkaContext extends ExecutionContext {
|
|
|
11
11
|
partition;
|
|
12
12
|
headers;
|
|
13
13
|
rawMessage;
|
|
14
|
-
heartbeat;
|
|
15
|
-
pause;
|
|
16
14
|
/**
|
|
17
15
|
* Initializes a new instance of the KafkaContext.
|
|
18
16
|
*
|
|
@@ -40,8 +38,6 @@ export class KafkaContext extends ExecutionContext {
|
|
|
40
38
|
this.topic = init.topic;
|
|
41
39
|
this.key = init.key;
|
|
42
40
|
this.payload = init.payload;
|
|
43
|
-
this.heartbeat = init.heartbeat;
|
|
44
|
-
this.pause = init.pause;
|
|
45
41
|
this.rawMessage = init.rawMessage;
|
|
46
42
|
}
|
|
47
43
|
}
|
package/package.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opra/kafka",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.28.1",
|
|
4
4
|
"description": "Opra Kafka adapter",
|
|
5
5
|
"author": "Panates",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"node-events-async": "^1.5.2",
|
|
9
9
|
"tslib": "^2.8.1",
|
|
10
|
-
"valgen": "^6.0
|
|
10
|
+
"valgen": "^6.1.0"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"@opra/common": "^1.
|
|
14
|
-
"@opra/core": "^1.
|
|
15
|
-
"
|
|
13
|
+
"@opra/common": "^1.28.1",
|
|
14
|
+
"@opra/core": "^1.28.1",
|
|
15
|
+
"@platformatic/kafka": ">= 1.34.0 <2"
|
|
16
16
|
},
|
|
17
17
|
"exports": {
|
|
18
18
|
".": {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function parseRegExp(str: string): RegExp;
|
package/parse-regexp.js
ADDED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { RequestParseFunction } from '../request-parser.js';
|
|
2
|
-
/**
|
|
3
|
-
* A parser function that returns the input buffer as-is.
|
|
4
|
-
*
|
|
5
|
-
* @param buffer - The buffer to be returned.
|
|
6
|
-
* @returns The original buffer.
|
|
7
|
-
*/
|
|
8
|
-
export declare const binaryParser: RequestParseFunction;
|
package/parsers/binary.parser.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { RequestParseFunction } from '../request-parser.js';
|
|
2
|
-
/**
|
|
3
|
-
* A parser function that converts the input buffer to a string.
|
|
4
|
-
*
|
|
5
|
-
* @param buffer - The buffer to be converted.
|
|
6
|
-
* @returns The buffer content as a string.
|
|
7
|
-
*/
|
|
8
|
-
export declare const stringParser: RequestParseFunction;
|
package/parsers/string.parser.js
DELETED
package/request-parser.d.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type definition for a function that parses a Buffer into a specific format.
|
|
3
|
-
*
|
|
4
|
-
* @param buffer - The buffer to be parsed.
|
|
5
|
-
* @returns The parsed result.
|
|
6
|
-
*/
|
|
7
|
-
export type RequestParseFunction = (buffer: Buffer) => any;
|
|
8
|
-
/**
|
|
9
|
-
* A registry of pre-defined request parsing functions.
|
|
10
|
-
*/
|
|
11
|
-
export declare const RequestParser: Record<string, RequestParseFunction>;
|
package/request-parser.js
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { binaryParser } from './parsers/binary.parser.js';
|
|
2
|
-
import { stringParser } from './parsers/string.parser.js';
|
|
3
|
-
/**
|
|
4
|
-
* A registry of pre-defined request parsing functions.
|
|
5
|
-
*/
|
|
6
|
-
export const RequestParser = {
|
|
7
|
-
/* Parses the buffer as raw binary data (returns the buffer as-is). */
|
|
8
|
-
BINARY: binaryParser,
|
|
9
|
-
/* Parses the buffer as a UTF-8 string. */
|
|
10
|
-
STRING: stringParser,
|
|
11
|
-
};
|