@aichatwar/shared 1.0.89 → 1.0.93
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.
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Consumer, EachMessagePayload } from "kafkajs";
|
|
2
2
|
import { BaseEvent } from '../baseEvent';
|
|
3
3
|
export declare abstract class Listener<T extends BaseEvent> {
|
|
4
|
-
abstract topic: T[
|
|
4
|
+
abstract topic: T['subject'];
|
|
5
5
|
abstract groupId: string;
|
|
6
|
-
abstract onMessage(data: T[
|
|
7
|
-
protected
|
|
8
|
-
|
|
9
|
-
constructor(
|
|
6
|
+
abstract onMessage(data: T['data'], payload: EachMessagePayload): Promise<void>;
|
|
7
|
+
protected consumer: Consumer;
|
|
8
|
+
protected ackDeadline: number;
|
|
9
|
+
constructor(consumer: Consumer);
|
|
10
10
|
listen(): Promise<void>;
|
|
11
11
|
}
|
|
@@ -10,26 +10,42 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.Listener = void 0;
|
|
13
|
-
// Updated event to base
|
|
14
13
|
class Listener {
|
|
15
|
-
constructor(
|
|
16
|
-
this.
|
|
14
|
+
constructor(consumer) {
|
|
15
|
+
this.ackDeadline = 5 * 1000; // 5 seconds
|
|
16
|
+
this.consumer = consumer;
|
|
17
17
|
}
|
|
18
18
|
listen() {
|
|
19
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
20
|
-
this.consumer = this.kafka.consumer({ groupId: this.groupId });
|
|
21
20
|
yield this.consumer.connect();
|
|
22
|
-
yield this.consumer.subscribe({
|
|
21
|
+
yield this.consumer.subscribe({
|
|
22
|
+
topic: this.topic,
|
|
23
|
+
fromBeginning: false,
|
|
24
|
+
});
|
|
25
|
+
console.log(`Listening to topic: ${this.topic} with groupId: ${this.groupId}`);
|
|
23
26
|
yield this.consumer.run({
|
|
24
27
|
eachMessage: (payload) => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
-
|
|
26
|
-
if (!message.value)
|
|
28
|
+
if (!payload.message.value)
|
|
27
29
|
return;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
console.log(`Message received -> topic: ${this.topic}, groupId: ${this.groupId}`);
|
|
31
|
+
try {
|
|
32
|
+
const data = JSON.parse(payload.message.value.toString());
|
|
33
|
+
yield this.onMessage(data, payload);
|
|
34
|
+
// Manual acknowledgment - commit the offset after successful processing
|
|
35
|
+
yield this.consumer.commitOffsets([{
|
|
36
|
+
topic: payload.topic,
|
|
37
|
+
partition: payload.partition,
|
|
38
|
+
offset: (BigInt(payload.message.offset) + BigInt(1)).toString()
|
|
39
|
+
}]);
|
|
40
|
+
console.log(`Message processed and acknowledged for topic: ${this.topic}`);
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
console.error(`Error processing message for topic: ${this.topic}`, error);
|
|
44
|
+
// In case of error, we don't commit the offset, so the message will be redelivered
|
|
45
|
+
throw error;
|
|
46
|
+
}
|
|
47
|
+
})
|
|
31
48
|
});
|
|
32
|
-
console.log(`Listening on Kafka topic ${this.topic}`);
|
|
33
49
|
});
|
|
34
50
|
}
|
|
35
51
|
}
|
|
@@ -3,6 +3,8 @@ import { BaseEvent } from '../baseEvent';
|
|
|
3
3
|
export declare abstract class Publisher<T extends BaseEvent> {
|
|
4
4
|
abstract topic: T['subject'];
|
|
5
5
|
protected producer: Producer;
|
|
6
|
+
protected maxRetries: number;
|
|
7
|
+
protected retryDelay: number;
|
|
6
8
|
constructor(producer: Producer);
|
|
7
9
|
publish(data: T['data']): Promise<void>;
|
|
8
10
|
}
|
|
@@ -12,22 +12,41 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
exports.Publisher = void 0;
|
|
13
13
|
class Publisher {
|
|
14
14
|
constructor(producer) {
|
|
15
|
+
this.maxRetries = 3;
|
|
16
|
+
this.retryDelay = 1000; // 1 second
|
|
15
17
|
this.producer = producer;
|
|
16
18
|
}
|
|
17
19
|
publish(data) {
|
|
18
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
19
21
|
if (!this.producer)
|
|
20
22
|
throw new Error('Producer not defined');
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
let lastError = null;
|
|
24
|
+
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
|
25
|
+
try {
|
|
26
|
+
yield this.producer.send({
|
|
27
|
+
topic: this.topic,
|
|
28
|
+
messages: [{
|
|
29
|
+
value: JSON.stringify(data),
|
|
30
|
+
key: data.id || undefined, // Use id as key for partitioning if available
|
|
31
|
+
timestamp: Date.now().toString()
|
|
32
|
+
}],
|
|
33
|
+
});
|
|
34
|
+
console.log(`Event published successfully: ${this.topic}`, data);
|
|
35
|
+
return; // Success, exit retry loop
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
lastError = err;
|
|
39
|
+
console.error(`❌ Publish attempt ${attempt}/${this.maxRetries} failed for ${this.topic}`, err);
|
|
40
|
+
if (attempt < this.maxRetries) {
|
|
41
|
+
console.log(`Retrying in ${this.retryDelay}ms...`);
|
|
42
|
+
yield new Promise(resolve => setTimeout(resolve, this.retryDelay));
|
|
43
|
+
this.retryDelay *= 2; // Exponential backoff
|
|
44
|
+
}
|
|
45
|
+
}
|
|
30
46
|
}
|
|
47
|
+
// All retries failed
|
|
48
|
+
console.error(`❌ Publish failed after ${this.maxRetries} attempts for ${this.topic}`);
|
|
49
|
+
throw lastError || new Error(`Failed to publish to ${this.topic} after ${this.maxRetries} attempts`);
|
|
31
50
|
});
|
|
32
51
|
}
|
|
33
52
|
}
|