@drarzter/kafka-client 0.6.3 → 0.6.4
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 +5 -2
- package/dist/{chunk-RGRKN4E5.mjs → chunk-7IX4AKQX.mjs} +44 -9
- package/dist/chunk-7IX4AKQX.mjs.map +1 -0
- package/dist/core.d.mts +13 -0
- package/dist/core.d.ts +13 -0
- package/dist/core.js +43 -8
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/index.d.mts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +45 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -20
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-RGRKN4E5.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -563,7 +563,7 @@ async function executeWithRetry(fn, ctx, deps) {
|
|
|
563
563
|
}
|
|
564
564
|
} else {
|
|
565
565
|
const cap = Math.min(backoffMs * 2 ** (attempt - 1), maxBackoffMs);
|
|
566
|
-
await sleep(Math.random() * cap);
|
|
566
|
+
await sleep(Math.floor(Math.random() * cap));
|
|
567
567
|
}
|
|
568
568
|
}
|
|
569
569
|
}
|
|
@@ -937,7 +937,8 @@ var KafkaClient = class {
|
|
|
937
937
|
kafka;
|
|
938
938
|
producer;
|
|
939
939
|
txProducer;
|
|
940
|
-
|
|
940
|
+
/** Maps transactionalId → Producer for each active retry level consumer. */
|
|
941
|
+
retryTxProducers = /* @__PURE__ */ new Map();
|
|
941
942
|
consumers = /* @__PURE__ */ new Map();
|
|
942
943
|
admin;
|
|
943
944
|
logger;
|
|
@@ -1203,18 +1204,32 @@ var KafkaClient = class {
|
|
|
1203
1204
|
this.consumerCreationOptions.delete(cGroupId);
|
|
1204
1205
|
this.logger.log(`Retry consumer disconnected: group "${cGroupId}"`);
|
|
1205
1206
|
}
|
|
1207
|
+
const txId = `${cGroupId}-tx`;
|
|
1208
|
+
const txProducer = this.retryTxProducers.get(txId);
|
|
1209
|
+
if (txProducer) {
|
|
1210
|
+
await txProducer.disconnect().catch(() => {
|
|
1211
|
+
});
|
|
1212
|
+
this.retryTxProducers.delete(txId);
|
|
1213
|
+
}
|
|
1206
1214
|
}
|
|
1207
1215
|
this.companionGroupIds.delete(groupId);
|
|
1208
1216
|
} else {
|
|
1209
|
-
const tasks =
|
|
1210
|
-
(
|
|
1211
|
-
|
|
1212
|
-
|
|
1217
|
+
const tasks = [
|
|
1218
|
+
...Array.from(this.consumers.values()).map(
|
|
1219
|
+
(c) => c.disconnect().catch(() => {
|
|
1220
|
+
})
|
|
1221
|
+
),
|
|
1222
|
+
...Array.from(this.retryTxProducers.values()).map(
|
|
1223
|
+
(p) => p.disconnect().catch(() => {
|
|
1224
|
+
})
|
|
1225
|
+
)
|
|
1226
|
+
];
|
|
1213
1227
|
await Promise.allSettled(tasks);
|
|
1214
1228
|
this.consumers.clear();
|
|
1215
1229
|
this.runningConsumers.clear();
|
|
1216
1230
|
this.consumerCreationOptions.clear();
|
|
1217
1231
|
this.companionGroupIds.clear();
|
|
1232
|
+
this.retryTxProducers.clear();
|
|
1218
1233
|
this.logger.log("All consumers disconnected");
|
|
1219
1234
|
}
|
|
1220
1235
|
}
|
|
@@ -1222,6 +1237,12 @@ var KafkaClient = class {
|
|
|
1222
1237
|
* Query consumer group lag per partition.
|
|
1223
1238
|
* Lag = broker high-watermark − last committed offset.
|
|
1224
1239
|
* A committed offset of -1 (nothing committed yet) counts as full lag.
|
|
1240
|
+
*
|
|
1241
|
+
* Returns an empty array when the consumer group has never committed any
|
|
1242
|
+
* offsets (freshly created group, `autoCommit: false` with no manual commits,
|
|
1243
|
+
* or group not yet assigned). This is a Kafka protocol limitation:
|
|
1244
|
+
* `fetchOffsets` only returns data for topic-partitions that have at least one
|
|
1245
|
+
* committed offset. Use `checkStatus()` to verify broker connectivity in that case.
|
|
1225
1246
|
*/
|
|
1226
1247
|
async getConsumerLag(groupId) {
|
|
1227
1248
|
const gid = groupId ?? this.defaultGroupId;
|
|
@@ -1270,7 +1291,7 @@ var KafkaClient = class {
|
|
|
1270
1291
|
tasks.push(this.txProducer.disconnect());
|
|
1271
1292
|
this.txProducer = void 0;
|
|
1272
1293
|
}
|
|
1273
|
-
for (const p of this.retryTxProducers) {
|
|
1294
|
+
for (const p of this.retryTxProducers.values()) {
|
|
1274
1295
|
tasks.push(p.disconnect());
|
|
1275
1296
|
}
|
|
1276
1297
|
this.retryTxProducers.clear();
|
|
@@ -1289,6 +1310,14 @@ var KafkaClient = class {
|
|
|
1289
1310
|
this.logger.log("All connections closed");
|
|
1290
1311
|
}
|
|
1291
1312
|
// ── Graceful shutdown ────────────────────────────────────────────
|
|
1313
|
+
/**
|
|
1314
|
+
* NestJS lifecycle hook — called automatically when the host module is torn down.
|
|
1315
|
+
* Drains in-flight handlers and disconnects all producers, consumers, and admin.
|
|
1316
|
+
* `KafkaModule` relies on this method; no separate destroy provider is needed.
|
|
1317
|
+
*/
|
|
1318
|
+
async onModuleDestroy() {
|
|
1319
|
+
await this.disconnect();
|
|
1320
|
+
}
|
|
1292
1321
|
/**
|
|
1293
1322
|
* Register SIGTERM / SIGINT handlers that drain in-flight messages before
|
|
1294
1323
|
* disconnecting. Call this once after constructing the client in non-NestJS apps.
|
|
@@ -1439,7 +1468,7 @@ var KafkaClient = class {
|
|
|
1439
1468
|
}
|
|
1440
1469
|
});
|
|
1441
1470
|
await p.connect();
|
|
1442
|
-
this.retryTxProducers.
|
|
1471
|
+
this.retryTxProducers.set(transactionalId, p);
|
|
1443
1472
|
return p;
|
|
1444
1473
|
}
|
|
1445
1474
|
async ensureTopic(topic2) {
|
|
@@ -1468,6 +1497,12 @@ var KafkaClient = class {
|
|
|
1468
1497
|
`Cannot use ${mode} on consumer group "${gid}" \u2014 it is already running with ${oppositeMode}. Use a different groupId for this consumer.`
|
|
1469
1498
|
);
|
|
1470
1499
|
}
|
|
1500
|
+
if (existingMode === mode) {
|
|
1501
|
+
const callerName = mode === "eachMessage" ? "startConsumer" : "startBatchConsumer";
|
|
1502
|
+
throw new Error(
|
|
1503
|
+
`${callerName}("${gid}") called twice \u2014 this group is already consuming. Call stopConsumer("${gid}") first or pass a different groupId.`
|
|
1504
|
+
);
|
|
1505
|
+
}
|
|
1471
1506
|
const consumer = getOrCreateConsumer(
|
|
1472
1507
|
gid,
|
|
1473
1508
|
fromBeginning,
|
|
@@ -1682,11 +1717,7 @@ var KafkaModule = class {
|
|
|
1682
1717
|
global: options.isGlobal ?? false,
|
|
1683
1718
|
module: KafkaModule,
|
|
1684
1719
|
imports: [import_core2.DiscoveryModule],
|
|
1685
|
-
providers: [
|
|
1686
|
-
kafkaClientProvider,
|
|
1687
|
-
KafkaModule.buildDestroyProvider(token),
|
|
1688
|
-
KafkaExplorer
|
|
1689
|
-
],
|
|
1720
|
+
providers: [kafkaClientProvider, KafkaExplorer],
|
|
1690
1721
|
exports: [kafkaClientProvider]
|
|
1691
1722
|
};
|
|
1692
1723
|
}
|
|
@@ -1702,11 +1733,7 @@ var KafkaModule = class {
|
|
|
1702
1733
|
global: asyncOptions.isGlobal ?? false,
|
|
1703
1734
|
module: KafkaModule,
|
|
1704
1735
|
imports: [...asyncOptions.imports || [], import_core2.DiscoveryModule],
|
|
1705
|
-
providers: [
|
|
1706
|
-
kafkaClientProvider,
|
|
1707
|
-
KafkaModule.buildDestroyProvider(token),
|
|
1708
|
-
KafkaExplorer
|
|
1709
|
-
],
|
|
1736
|
+
providers: [kafkaClientProvider, KafkaExplorer],
|
|
1710
1737
|
exports: [kafkaClientProvider]
|
|
1711
1738
|
};
|
|
1712
1739
|
}
|
|
@@ -1728,15 +1755,6 @@ var KafkaModule = class {
|
|
|
1728
1755
|
await client.connectProducer();
|
|
1729
1756
|
return client;
|
|
1730
1757
|
}
|
|
1731
|
-
static buildDestroyProvider(token) {
|
|
1732
|
-
return {
|
|
1733
|
-
provide: `${token}_DESTROY`,
|
|
1734
|
-
useFactory: (client) => ({
|
|
1735
|
-
onModuleDestroy: () => client.disconnect()
|
|
1736
|
-
}),
|
|
1737
|
-
inject: [token]
|
|
1738
|
-
};
|
|
1739
|
-
}
|
|
1740
1758
|
};
|
|
1741
1759
|
KafkaModule = __decorateClass([
|
|
1742
1760
|
(0, import_common3.Module)({})
|