@itentialopensource/adapter-kafkav2 0.26.4 → 0.26.6
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/CHANGELOG.md +16 -0
- package/adapter.js +110 -24
- package/package.json +5 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
|
|
2
|
+
## 0.26.6 [03-17-2026]
|
|
3
|
+
|
|
4
|
+
* fix console and bad variable
|
|
5
|
+
|
|
6
|
+
See merge request itentialopensource/adapters/adapter-kafkav2!68
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 0.26.5 [03-04-2026]
|
|
11
|
+
|
|
12
|
+
* Changes made at 2026.03.04_09:07AM
|
|
13
|
+
|
|
14
|
+
See merge request itentialopensource/adapters/adapter-kafkav2!67
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
2
18
|
## 0.26.4 [02-23-2026]
|
|
3
19
|
|
|
4
20
|
* Changes made at 2026.02.22_15:50PM
|
package/adapter.js
CHANGED
|
@@ -40,7 +40,18 @@ function consoleLoggerProvider(name) {
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
// add the compression codecs so that compressed messages can be consumed
|
|
44
|
+
// zstd has an issue in the pipeline
|
|
45
|
+
const {
|
|
46
|
+
Kafka, logLevel, CompressionTypes, CompressionCodecs
|
|
47
|
+
} = require('kafkajs');
|
|
48
|
+
const LZ4 = require('kafka-lz4-lite');
|
|
49
|
+
const SnappyCodec = require('kafkajs-snappy');
|
|
50
|
+
// const ZstdCodec = require('@kafkajs/zstd');
|
|
51
|
+
|
|
52
|
+
CompressionCodecs[CompressionTypes.LZ4] = LZ4.codec;
|
|
53
|
+
CompressionCodecs[CompressionTypes.Snappy] = SnappyCodec;
|
|
54
|
+
// CompressionCodecs[CompressionTypes.ZSTD] = ZstdCodec();
|
|
44
55
|
|
|
45
56
|
const LogLevelEnum = {
|
|
46
57
|
NOTHING: logLevel.NOTHING,
|
|
@@ -232,12 +243,12 @@ function formatErrorObject(origin, type, variables, sysCode, sysRes, stack) {
|
|
|
232
243
|
*/
|
|
233
244
|
function createSocketFactory(socketOptions, useSSL) {
|
|
234
245
|
return (options) => {
|
|
235
|
-
|
|
246
|
+
log.info('KafkaJS Socket Options:', options); // See what KafkaJS is actually passing
|
|
236
247
|
|
|
237
248
|
// Destructure properties from the options object
|
|
238
249
|
const { host, port, ssl } = options;
|
|
239
250
|
const brokerAddress = `${host}:${port}`;
|
|
240
|
-
|
|
251
|
+
log.info(
|
|
241
252
|
`Connecting to Kafka broker: ${brokerAddress} (${host}:${port}) ${useSSL ? 'with SSL' : 'without SSL'
|
|
242
253
|
}`
|
|
243
254
|
);
|
|
@@ -259,8 +270,8 @@ function createSocketFactory(socketOptions, useSSL) {
|
|
|
259
270
|
socket.setKeepAlive(keepAliveEnabled, keepAliveInterval);
|
|
260
271
|
socket.setTimeout(socketTimeout);
|
|
261
272
|
|
|
262
|
-
socket.on('error', (err) =>
|
|
263
|
-
socket.on('timeout', () =>
|
|
273
|
+
socket.on('error', (err) => log.error(`Socket error with ${brokerAddress}:`, err));
|
|
274
|
+
socket.on('timeout', () => log.warn(`Socket timeout with ${brokerAddress}`));
|
|
264
275
|
|
|
265
276
|
return socket;
|
|
266
277
|
};
|
|
@@ -540,6 +551,7 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
540
551
|
this.consumer = null;
|
|
541
552
|
this.registryUrl = null;
|
|
542
553
|
this.registry = 'abc';
|
|
554
|
+
this.consumerDisconnecting = false;
|
|
543
555
|
if (this.props && this.props.registry_url) {
|
|
544
556
|
this.registryUrl = this.props.registry_url;
|
|
545
557
|
this.registry = require('avro-schema-registry')(this.props.registry_url);
|
|
@@ -763,6 +775,18 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
763
775
|
return matched;
|
|
764
776
|
};
|
|
765
777
|
|
|
778
|
+
// Handle multiple disconnect requests
|
|
779
|
+
const safeConsumerDisconnect = async () => {
|
|
780
|
+
if (this.consumerDisconnecting) return;
|
|
781
|
+
this.consumerDisconnecting = true;
|
|
782
|
+
try {
|
|
783
|
+
await this.consumer.disconnect();
|
|
784
|
+
log.error('Consumer disconnected');
|
|
785
|
+
} catch (_) {
|
|
786
|
+
// ignore disconnect errors during shutdown
|
|
787
|
+
}
|
|
788
|
+
};
|
|
789
|
+
|
|
766
790
|
const run = async () => {
|
|
767
791
|
this.emit('ONLINE', {
|
|
768
792
|
id: this.id
|
|
@@ -821,6 +845,30 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
821
845
|
}
|
|
822
846
|
));
|
|
823
847
|
|
|
848
|
+
// Register a listener for the consumer crash event
|
|
849
|
+
this.consumer.on(this.consumer.events.CRASH, (e) => {
|
|
850
|
+
log.error(`Consumer crashed: ${JSON.stringify(e)}`, e.payload.error.stack);
|
|
851
|
+
setTimeout(() => {
|
|
852
|
+
// process.exit(1); // Or implement a restart mechanism
|
|
853
|
+
throw new Error(JSON.stringify(e));
|
|
854
|
+
}, 1000);
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
// Register a listener for the consumer disconnect event
|
|
858
|
+
this.consumer.on(this.consumer.events.DISCONNECT, (e) => {
|
|
859
|
+
this.consumerDisconnecting = true;
|
|
860
|
+
log.error(`Consumer disconnected: ${JSON.stringify(e)}`);
|
|
861
|
+
setTimeout(() => {
|
|
862
|
+
// process.exit(1); // Or implement a restart mechanism
|
|
863
|
+
throw new Error(JSON.stringify(e));
|
|
864
|
+
}, 1000);
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
// Register a listener for the consumer request_timeout event
|
|
868
|
+
this.consumer.on(this.consumer.events.REQUEST_TIMEOUT, (e) => {
|
|
869
|
+
log.error(`Consumer request timed out: ${JSON.stringify(e)}`);
|
|
870
|
+
});
|
|
871
|
+
|
|
824
872
|
const runPromise = this.consumer.run({
|
|
825
873
|
eachMessage: async ({ topic, partition, message }) => {
|
|
826
874
|
log.info(`PROCESSING NEW MESSAGE ON TOPIC: ${topic} PARTITION: ${partition} WITH OFFSET: ${message.offset}`);
|
|
@@ -892,11 +940,11 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
892
940
|
}
|
|
893
941
|
|
|
894
942
|
if (desiredTopic.length !== 0 && allowedPartition) {
|
|
895
|
-
log.info(
|
|
943
|
+
log.info('Message being CONSUMED as it does meet the filter condition');
|
|
896
944
|
if (desiredTopic.every((val) => mytopics.includes(val))) {
|
|
897
945
|
log.info(`Emitting: ${message.value.toString()} TO ${desiredTopic}`);
|
|
898
946
|
} else {
|
|
899
|
-
log.
|
|
947
|
+
log.warn(`The desired topic ${desiredTopic} does not exist. If it should, make sure it is in pronghorn.json`);
|
|
900
948
|
log.info(`Emitting: ${newMsg.value.toString()} TO kafka`);
|
|
901
949
|
desiredTopic = 'kafka';
|
|
902
950
|
}
|
|
@@ -906,16 +954,30 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
906
954
|
try {
|
|
907
955
|
messageObj = { [wrapper]: JSON.parse(newMsg.value) };
|
|
908
956
|
} catch (ex) {
|
|
909
|
-
|
|
957
|
+
try {
|
|
958
|
+
messageObj = { [wrapper]: newMsg.value.toString() };
|
|
959
|
+
} catch (excep) {
|
|
960
|
+
log.error(`Failed to wrap message content: ${excep.message}`, excep);
|
|
961
|
+
}
|
|
910
962
|
}
|
|
911
963
|
for (let j = 0; j < desiredTopic.length; j += 1) {
|
|
912
|
-
|
|
913
|
-
|
|
964
|
+
try {
|
|
965
|
+
messageObj.topic = topic;
|
|
966
|
+
eventSystem.publish(desiredTopic[j], messageObj);
|
|
967
|
+
} catch (ex) {
|
|
968
|
+
log.error(`Failed to publish to eventSystem topic '${desiredTopic[j]}': ${ex.message}`, ex);
|
|
969
|
+
log.error(`Failed message content: ${messageObj}`);
|
|
970
|
+
}
|
|
914
971
|
}
|
|
915
972
|
} else {
|
|
916
973
|
for (let j = 0; j < desiredTopic.length; j += 1) {
|
|
917
|
-
|
|
918
|
-
|
|
974
|
+
try {
|
|
975
|
+
newMsg.topic = topic;
|
|
976
|
+
eventSystem.publish(desiredTopic[j], newMsg);
|
|
977
|
+
} catch (ex) {
|
|
978
|
+
log.error(`Failed to publish to eventSystem topic '${desiredTopic[j]}': ${ex.message}`, ex);
|
|
979
|
+
log.error(`Failed message content: ${newMsg}`);
|
|
980
|
+
}
|
|
919
981
|
}
|
|
920
982
|
}
|
|
921
983
|
} else {
|
|
@@ -931,20 +993,27 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
931
993
|
|
|
932
994
|
await runPromise;
|
|
933
995
|
};
|
|
934
|
-
run().catch((err) =>
|
|
996
|
+
run().catch((err) => {
|
|
997
|
+
log.error(`[consumer] ${err.message}`, err);
|
|
998
|
+
throw new Error(JSON.stringify(err));
|
|
999
|
+
});
|
|
935
1000
|
|
|
936
1001
|
const errorTypes = ['unhandledRejection', 'uncaughtException'];
|
|
937
1002
|
const signalTraps = ['SIGTERM', 'SIGINT', 'SIGUSR2'];
|
|
938
1003
|
|
|
939
1004
|
errorTypes.forEach((type) => {
|
|
940
|
-
process.on(type, async (
|
|
1005
|
+
process.on(type, async (err) => {
|
|
941
1006
|
try {
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
await
|
|
945
|
-
|
|
1007
|
+
log.error(`Kafka Consumer Error - process.on ${type}`);
|
|
1008
|
+
log.error(err, err.stack);
|
|
1009
|
+
await safeConsumerDisconnect();
|
|
1010
|
+
setTimeout(() => {
|
|
1011
|
+
process.exit(0); // Or implement a restart mechanism
|
|
1012
|
+
}, 1000);
|
|
946
1013
|
} catch (_) {
|
|
947
|
-
|
|
1014
|
+
setTimeout(() => {
|
|
1015
|
+
process.exit(1); // Or implement a restart mechanism
|
|
1016
|
+
}, 1000);
|
|
948
1017
|
}
|
|
949
1018
|
});
|
|
950
1019
|
});
|
|
@@ -952,7 +1021,7 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
952
1021
|
signalTraps.forEach((type) => {
|
|
953
1022
|
process.once(type, async () => {
|
|
954
1023
|
try {
|
|
955
|
-
await
|
|
1024
|
+
await safeConsumerDisconnect();
|
|
956
1025
|
} finally {
|
|
957
1026
|
process.kill(process.pid, type);
|
|
958
1027
|
}
|
|
@@ -1030,6 +1099,11 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
1030
1099
|
|
|
1031
1100
|
const run = async () => {
|
|
1032
1101
|
try {
|
|
1102
|
+
// Register a listener for the producer request_timeout event
|
|
1103
|
+
this.producer.on(this.producer.events.REQUEST_TIMEOUT, (e) => {
|
|
1104
|
+
log.error(`Producer request timed out: ${JSON.stringify(e)}`);
|
|
1105
|
+
});
|
|
1106
|
+
|
|
1033
1107
|
const topicMessages = payloads;
|
|
1034
1108
|
// need to go through the payloads that were provided
|
|
1035
1109
|
for (let p = 0; p < payloads.length; p += 1) {
|
|
@@ -1043,12 +1117,18 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
1043
1117
|
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
1044
1118
|
return callback(null, errorObj);
|
|
1045
1119
|
}
|
|
1120
|
+
if (!Array.isArray(payloads[p].messages)) {
|
|
1121
|
+
const errorObj = formatErrorObject(origin, 'Invalid payloads format - messages must be an array', null, null, null, null);
|
|
1122
|
+
log.error(`${origin}: ${errorObj.IAPerror.displayString}`);
|
|
1123
|
+
return callback(null, errorObj);
|
|
1124
|
+
}
|
|
1046
1125
|
topicMessages[p].messages = payloads[p].messages.map((message) => {
|
|
1047
1126
|
if (typeof message.value === 'object') {
|
|
1048
1127
|
return { ...message, value: JSON.stringify(message.value) };
|
|
1049
1128
|
}
|
|
1050
1129
|
return message;
|
|
1051
1130
|
});
|
|
1131
|
+
log.debug(`Sending message(s) to topic: ${payloads[p].topic}`);
|
|
1052
1132
|
if (this.registry && topicMessages[p].simple && topicMessages[p].simple.toUpperCase() === 'NO') {
|
|
1053
1133
|
log.debug(`Handling AVRO Message: ${JSON.stringify(topicMessages[p])}`);
|
|
1054
1134
|
let keyVer = 1;
|
|
@@ -1113,6 +1193,7 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
1113
1193
|
}
|
|
1114
1194
|
await this.producer.connect();
|
|
1115
1195
|
await this.producer.sendBatch({ topicMessages });
|
|
1196
|
+
log.debug(`Sent message to broker: ${JSON.stringify(topicMessages)}`);
|
|
1116
1197
|
} catch (err) {
|
|
1117
1198
|
const errorObj = formatErrorObject(origin, 'Producer sending message failed', null, null, null, err);
|
|
1118
1199
|
log.error('error: '.concat(err));
|
|
@@ -1130,13 +1211,18 @@ class Kafkav2 extends AdapterBaseCl {
|
|
|
1130
1211
|
const signalTraps = ['SIGTERM', 'SIGINT', 'SIGUSR2'];
|
|
1131
1212
|
|
|
1132
1213
|
errorTypes.forEach((type) => {
|
|
1133
|
-
process.on(type, async () => {
|
|
1214
|
+
process.on(type, async (err) => {
|
|
1134
1215
|
try {
|
|
1135
|
-
|
|
1216
|
+
log.error(`Kafka Producer Error - process.on ${type}`);
|
|
1217
|
+
log.error(err, err.stack);
|
|
1136
1218
|
await this.producer.disconnect();
|
|
1137
|
-
|
|
1219
|
+
setTimeout(() => {
|
|
1220
|
+
process.exit(0); // Or implement a restart mechanism
|
|
1221
|
+
}, 1000);
|
|
1138
1222
|
} catch (_) {
|
|
1139
|
-
|
|
1223
|
+
setTimeout(() => {
|
|
1224
|
+
process.exit(1); // Or implement a restart mechanism
|
|
1225
|
+
}, 1000);
|
|
1140
1226
|
}
|
|
1141
1227
|
});
|
|
1142
1228
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@itentialopensource/adapter-kafkav2",
|
|
3
|
-
"version": "0.26.
|
|
3
|
+
"version": "0.26.6",
|
|
4
4
|
"description": "Itential adapter to connect to kafka",
|
|
5
5
|
"main": "adapter.js",
|
|
6
6
|
"scripts": {
|
|
@@ -40,10 +40,12 @@
|
|
|
40
40
|
"ajv": "8.18.0",
|
|
41
41
|
"avro-schema-registry": "2.1.0",
|
|
42
42
|
"avsc": "5.4.21",
|
|
43
|
-
"axios": "1.13.
|
|
43
|
+
"axios": "1.13.6",
|
|
44
44
|
"fs-extra": "11.3.3",
|
|
45
45
|
"json-query": "2.2.2",
|
|
46
|
-
"kafkajs": "2.2.
|
|
46
|
+
"kafkajs": "2.2.4",
|
|
47
|
+
"kafka-lz4-lite": "1.0.5",
|
|
48
|
+
"kafkajs-snappy": "1.1.0",
|
|
47
49
|
"mongodb": "4.17.2",
|
|
48
50
|
"readline-sync": "1.4.10",
|
|
49
51
|
"uuid": "3.0.1",
|