@aichatwar/shared 1.0.126 → 1.0.128
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.
|
@@ -6,6 +6,7 @@ export declare abstract class Listener<T extends BaseEvent> {
|
|
|
6
6
|
abstract onMessage(data: T['data'], payload: EachMessagePayload): Promise<void>;
|
|
7
7
|
protected consumer: Consumer;
|
|
8
8
|
protected ackDeadline: number;
|
|
9
|
+
protected fromBeginning: boolean;
|
|
9
10
|
private currentPayload?;
|
|
10
11
|
private retryCount;
|
|
11
12
|
private readonly maxInitialRetries;
|
|
@@ -13,6 +13,7 @@ exports.Listener = void 0;
|
|
|
13
13
|
class Listener {
|
|
14
14
|
constructor(consumer) {
|
|
15
15
|
this.ackDeadline = 5 * 1000; // 5 seconds
|
|
16
|
+
this.fromBeginning = false; // Override in subclasses to read from beginning
|
|
16
17
|
this.retryCount = 0;
|
|
17
18
|
this.maxInitialRetries = 3; // Show detailed retry logs for first 3 attempts
|
|
18
19
|
this.maxRetryDelay = 60000; // Cap delay at 60 seconds
|
|
@@ -67,10 +68,10 @@ class Listener {
|
|
|
67
68
|
yield this.consumer.connect();
|
|
68
69
|
console.log(`✅ [${this.topic}] Consumer connected`);
|
|
69
70
|
// Crash handler is set up in constructor, no need to add it again
|
|
70
|
-
console.log(`📋 [${this.topic}] Subscribing to topic
|
|
71
|
+
console.log(`📋 [${this.topic}] Subscribing to topic... (fromBeginning: ${this.fromBeginning})`);
|
|
71
72
|
yield this.consumer.subscribe({
|
|
72
73
|
topic: this.topic,
|
|
73
|
-
fromBeginning:
|
|
74
|
+
fromBeginning: this.fromBeginning,
|
|
74
75
|
});
|
|
75
76
|
console.log(`✅ [${this.topic}] Successfully subscribed to topic with groupId: ${this.groupId}`);
|
|
76
77
|
// Log success message, especially if there were previous retries
|
|
@@ -79,14 +80,22 @@ class Listener {
|
|
|
79
80
|
}
|
|
80
81
|
// Reset retry count on successful connection
|
|
81
82
|
this.retryCount = 0;
|
|
83
|
+
console.log(`🚀 [${this.topic}] About to call consumer.run() with groupId: ${this.groupId}`);
|
|
82
84
|
console.log(`🚀 [${this.topic}] Starting consumer.run() with groupId: ${this.groupId}`);
|
|
85
|
+
console.log(`🚀 [${this.topic}] Consumer configuration:`, {
|
|
86
|
+
groupId: this.groupId,
|
|
87
|
+
topic: this.topic,
|
|
88
|
+
fromBeginning: this.fromBeginning,
|
|
89
|
+
autoCommit: false,
|
|
90
|
+
});
|
|
83
91
|
yield this.consumer.run({
|
|
84
92
|
// CRITICAL: Disable auto-commit to prevent message loss during rebalancing
|
|
85
93
|
// Offsets are only committed when we explicitly call ack()
|
|
86
94
|
autoCommit: false,
|
|
87
95
|
eachMessage: (payload) => __awaiter(this, void 0, void 0, function* () {
|
|
88
|
-
|
|
96
|
+
console.log(`📨 [${this.topic}] eachMessage callback invoked! -> groupId: ${this.groupId}, partition: ${payload.partition}, offset: ${payload.message.offset}, topic: ${payload.topic}`);
|
|
89
97
|
if (!payload.message.value) {
|
|
98
|
+
console.warn(`⚠️ [${this.topic}] Empty message value at offset ${payload.message.offset}, acknowledging...`);
|
|
90
99
|
// Acknowledge empty messages to avoid blocking
|
|
91
100
|
yield this.consumer.commitOffsets([{
|
|
92
101
|
topic: payload.topic,
|
|
@@ -95,7 +104,9 @@ class Listener {
|
|
|
95
104
|
}]);
|
|
96
105
|
return;
|
|
97
106
|
}
|
|
98
|
-
|
|
107
|
+
// Commented out key logging as requested
|
|
108
|
+
// console.log(`📨 [${this.topic}] Message received -> groupId: ${this.groupId}, partition: ${payload.partition}, offset: ${payload.message.offset}, key: ${payload.message.key?.toString() || 'none'}`);
|
|
109
|
+
console.log(`📨 [${this.topic}] Message received -> groupId: ${this.groupId}, partition: ${payload.partition}, offset: ${payload.message.offset}, value length: ${payload.message.value.toString().length}`);
|
|
99
110
|
// Store current payload for manual ack
|
|
100
111
|
this.currentPayload = payload;
|
|
101
112
|
try {
|
|
@@ -106,7 +117,7 @@ class Listener {
|
|
|
106
117
|
// This ensures at-least-once delivery semantics
|
|
107
118
|
}
|
|
108
119
|
catch (error) {
|
|
109
|
-
console.error(
|
|
120
|
+
console.error(`❌ [${this.topic}] Error processing message for topic: ${this.topic}, offset: ${payload.message.offset}`, error);
|
|
110
121
|
// In case of error, we don't commit the offset, so the message will be redelivered
|
|
111
122
|
// This ensures failed messages are retried
|
|
112
123
|
throw error;
|
|
@@ -115,8 +126,14 @@ class Listener {
|
|
|
115
126
|
// Clear the current payload
|
|
116
127
|
this.currentPayload = undefined;
|
|
117
128
|
}
|
|
118
|
-
})
|
|
129
|
+
}),
|
|
130
|
+
eachBatch: (_a) => __awaiter(this, [_a], void 0, function* ({ batch, resolveOffset, heartbeat }) {
|
|
131
|
+
var _b, _c;
|
|
132
|
+
// Log batch processing for debugging
|
|
133
|
+
console.log(`📦 [${this.topic}] Processing batch: ${batch.messages.length} messages, partition: ${batch.partition}, first offset: ${(_b = batch.messages[0]) === null || _b === void 0 ? void 0 : _b.offset}, last offset: ${(_c = batch.messages[batch.messages.length - 1]) === null || _c === void 0 ? void 0 : _c.offset}`);
|
|
134
|
+
}),
|
|
119
135
|
});
|
|
136
|
+
console.log(`✅ [${this.topic}] consumer.run() call completed (this is expected - run() is async and continues running)`);
|
|
120
137
|
// Mark as successfully listening only after subscription and run are successful
|
|
121
138
|
this.isListening = true;
|
|
122
139
|
}
|
|
@@ -24,12 +24,10 @@ class Publisher {
|
|
|
24
24
|
let lastError = null;
|
|
25
25
|
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
|
|
26
26
|
try {
|
|
27
|
-
const messageKey = data.id || undefined; // Use id as key for partitioning if available
|
|
28
27
|
const result = yield this.producer.send({
|
|
29
28
|
topic: this.topic,
|
|
30
29
|
messages: [{
|
|
31
30
|
value: JSON.stringify(data),
|
|
32
|
-
key: messageKey,
|
|
33
31
|
timestamp: Date.now().toString()
|
|
34
32
|
}],
|
|
35
33
|
});
|
|
@@ -37,7 +35,6 @@ class Publisher {
|
|
|
37
35
|
topic: this.topic,
|
|
38
36
|
partition: (_a = result[0]) === null || _a === void 0 ? void 0 : _a.partition,
|
|
39
37
|
offset: (_b = result[0]) === null || _b === void 0 ? void 0 : _b.offset,
|
|
40
|
-
key: (messageKey === null || messageKey === void 0 ? void 0 : messageKey.toString()) || 'none',
|
|
41
38
|
data: JSON.stringify(data).substring(0, 200) // First 200 chars for brevity
|
|
42
39
|
});
|
|
43
40
|
return; // Success, exit retry loop
|