@itentialopensource/adapter-kafkav2 0.23.3 → 0.23.5

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/README.md CHANGED
@@ -157,6 +157,14 @@ Sample SSL and SASL properties that go under client props. In the below example
157
157
  }
158
158
  ```
159
159
 
160
+ Sample socket properties
161
+ ```json
162
+ "socketOptions": {
163
+ "keepAlive": true,
164
+ "keepAliveInterval": 45000,
165
+ "socketTimeout": 20000
166
+ }
167
+ ```
160
168
 
161
169
  ### Topic Properties
162
170
 
@@ -311,6 +319,7 @@ The following properties are used to define the Kafka Client. These properties a
311
319
  | retry -> retries | Max number of retries per call. default: 5 |
312
320
  | ssl | Object, options to be passed to the tls broker sockets, ex. { rejectUnauthorized: false }.|
313
321
  | sasl | Object, SASL authentication configuration (Currently, supports PLAIN, SCRAM-SHA-256, SCRAM-SHA-512), ex. { mechanism: 'plain', username: 'foo', password: 'bar' }.|
322
+ | socketOptions | Object, Socket Options: Configuration for socket behavior, including keep-alive, interval, and timeout settings.|
314
323
 
315
324
  For all client config options see [Client Config](https://kafka.js.org/docs/configuration)
316
325
 
package/adapter.js CHANGED
@@ -17,11 +17,16 @@
17
17
  const fs = require('fs-extra');
18
18
  const path = require('path');
19
19
  const util = require('util');
20
+ const net = require('net');
21
+ const tls = require('tls');
20
22
  /* Fetch in the other needed components for the this Adaptor */
21
23
  // const EventEmitterCl = require('events').EventEmitter;
22
24
  const AdapterBaseCl = require(path.join(__dirname, 'adapterBase.js'));
23
25
  const DBUtil = require(path.join(__dirname, 'utils', 'dbUtil.js'));
24
26
 
27
+ const DEFAULT_KEEP_ALIVE_INTERVAL = 60000; // 60s
28
+ const DEFAULT_SOCKET_TIMEOUT = 30000; // 30s
29
+
25
30
  const axios = require('axios');
26
31
 
27
32
  let needRestart = false;
@@ -216,6 +221,51 @@ function formatErrorObject(origin, type, variables, sysCode, sysRes, stack) {
216
221
  return errorObject;
217
222
  }
218
223
 
224
+ /**
225
+ * @summary Creates a socket factory for KafkaJS to handle custom socket connections.
226
+ *
227
+ * @function createSocketFactory
228
+ * @param {Object} socketOptions - Configuration options for the socket connection.
229
+ * @param {Boolean} useSSL - Determines whether SSL should be used for the connection.
230
+ *
231
+ * @return {Function} - A socket factory function that establishes a connection to Kafka brokers.
232
+ */
233
+ function createSocketFactory(socketOptions, useSSL) {
234
+ return (options) => {
235
+ console.log('KafkaJS Socket Options:', options); // See what KafkaJS is actually passing
236
+
237
+ // Destructure properties from the options object
238
+ const { host, port, ssl } = options;
239
+ const brokerAddress = `${host}:${port}`;
240
+ console.log(
241
+ `Connecting to Kafka broker: ${brokerAddress} (${host}:${port}) ${useSSL ? 'with SSL' : 'without SSL'
242
+ }`
243
+ );
244
+
245
+ const socket = useSSL
246
+ ? tls.connect({ host, port, rejectUnauthorized: false }) // Use TLS for SSL
247
+ : net.createConnection({ host, port }); // Use Net for Non-SSL
248
+
249
+ const keepAliveEnabled = socketOptions && socketOptions.keepAlive !== undefined
250
+ ? socketOptions.keepAlive
251
+ : true;
252
+ const keepAliveInterval = socketOptions && socketOptions.keepAliveInterval !== undefined
253
+ ? socketOptions.keepAliveInterval
254
+ : DEFAULT_KEEP_ALIVE_INTERVAL; // 60s default
255
+ const socketTimeout = socketOptions && socketOptions.socketTimeout !== undefined
256
+ ? socketOptions.socketTimeout
257
+ : DEFAULT_SOCKET_TIMEOUT; // 30s default
258
+
259
+ socket.setKeepAlive(keepAliveEnabled, keepAliveInterval);
260
+ socket.setTimeout(socketTimeout);
261
+
262
+ socket.on('error', (err) => console.error(`Socket error with ${brokerAddress}:`, err));
263
+ socket.on('timeout', () => console.warn(`Socket timeout with ${brokerAddress}`));
264
+
265
+ return socket;
266
+ };
267
+ }
268
+
219
269
  /**
220
270
  * This is the adapter/interface into Kafka
221
271
  */
@@ -645,6 +695,14 @@ class Kafkav2 extends AdapterBaseCl {
645
695
  log.info('EMITTED ONLINE ON STUB MODE');
646
696
  return;
647
697
  }
698
+ const combinedProps = this.props.client || {};
699
+ // Extract socket options with default values
700
+ const socketOptions = this.props.client.socketOptions || null;
701
+ const useSSL = this.props.client.ssl || false; // Determine SSL usage
702
+
703
+ if (socketOptions) {
704
+ combinedProps.socketFactory = createSocketFactory(socketOptions, useSSL);
705
+ }
648
706
 
649
707
  if (!needRestart) {
650
708
  try {
@@ -653,7 +711,7 @@ class Kafkav2 extends AdapterBaseCl {
653
711
  this.props.client.logLevel = logLevelEnum;
654
712
  }
655
713
  // Create a kafka client
656
- const combinedProps = this.props.client || {};
714
+
657
715
  if (this.props.client.ssl && this.props.client.ssl.ca) {
658
716
  combinedProps.ssl.ca = [fs.readFileSync(this.props.client.ssl.ca, 'utf-8')];
659
717
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itentialopensource/adapter-kafkav2",
3
- "version": "0.23.3",
3
+ "version": "0.23.5",
4
4
  "description": "Itential adapter to connect to kafka",
5
5
  "main": "adapter.js",
6
6
  "wizardVersion": "2.35.0",
@@ -46,7 +46,7 @@
46
46
  "ajv": "^8.17.1",
47
47
  "avro-schema-registry": "^2.1.0",
48
48
  "avsc": "^5.4.21",
49
- "axios": "^1.7.9",
49
+ "axios": "^1.8.2",
50
50
  "fs-extra": "^11.2.0",
51
51
  "json-query": "^2.2.2",
52
52
  "kafkajs": "2.2.3",
@@ -21,16 +21,18 @@
21
21
  ]
22
22
  }
23
23
  },
24
- "parseMessage" :{
24
+ "parseMessage": {
25
25
  "type": "boolean",
26
26
  "description": "Whether or not to prase the message as JSON when consumed by IAP",
27
- "default" : true
27
+ "default": true
28
28
  },
29
- "wrapMessage" : {
29
+ "wrapMessage": {
30
30
  "type": "string",
31
31
  "description": "A key to wrap the parsed JSON message",
32
- "examples" : [ "message"],
33
- "default" : "payload"
32
+ "examples": [
33
+ "message"
34
+ ],
35
+ "default": "payload"
34
36
  },
35
37
  "interval_time": {
36
38
  "type": "integer",
@@ -79,6 +81,26 @@
79
81
  },
80
82
  "sasl": {
81
83
  "type": "object"
84
+ },
85
+ "socketOptions": {
86
+ "type": "object",
87
+ "properties": {
88
+ "keepAlive": {
89
+ "type": "boolean",
90
+ "description": "Whether to enable keep-alive on the socket."
91
+ },
92
+ "keepAliveInterval": {
93
+ "type": "integer",
94
+ "minimum": 0,
95
+ "description": "Interval (in milliseconds) for keep-alive packets."
96
+ },
97
+ "socketTimeout": {
98
+ "type": "integer",
99
+ "minimum": 0,
100
+ "description": "Timeout (in milliseconds) for socket inactivity before closing."
101
+ }
102
+ },
103
+ "additionalProperties": false
82
104
  }
83
105
  }
84
106
  },
@@ -37,6 +37,11 @@
37
37
  "username": "my-user",
38
38
  "password": "my-password",
39
39
  "mechanism": "scram-sha-512"
40
+ },
41
+ "socketOptions": {
42
+ "keepAlive": true,
43
+ "keepAliveInterval": 45000,
44
+ "socketTimeout": 20000
40
45
  }
41
46
  },
42
47
  "producer": {