@aichatwar/shared 1.0.103 → 1.0.104

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.
@@ -8,7 +8,9 @@ export declare abstract class Listener<T extends BaseEvent> {
8
8
  protected ackDeadline: number;
9
9
  private currentPayload?;
10
10
  private retryCount;
11
- private readonly maxRetries;
11
+ private readonly maxInitialRetries;
12
+ private readonly maxRetryDelay;
13
+ private isListening;
12
14
  constructor(consumer: Consumer);
13
15
  ack(): Promise<void>;
14
16
  listen(): Promise<void>;
@@ -14,7 +14,9 @@ class Listener {
14
14
  constructor(consumer) {
15
15
  this.ackDeadline = 5 * 1000; // 5 seconds
16
16
  this.retryCount = 0;
17
- this.maxRetries = 5;
17
+ this.maxInitialRetries = 5; // Show detailed retry logs for first 5 attempts
18
+ this.maxRetryDelay = 60000; // Cap delay at 60 seconds
19
+ this.isListening = false; // Track if listener is active
18
20
  this.consumer = consumer;
19
21
  }
20
22
  // Manual acknowledgment method
@@ -34,6 +36,10 @@ class Listener {
34
36
  listen() {
35
37
  return __awaiter(this, void 0, void 0, function* () {
36
38
  var _a;
39
+ // Prevent multiple simultaneous listen attempts
40
+ if (this.isListening) {
41
+ return;
42
+ }
37
43
  try {
38
44
  yield this.consumer.connect();
39
45
  // Handle consumer errors (including partition errors)
@@ -53,7 +59,7 @@ class Listener {
53
59
  });
54
60
  // Reset retry count on successful connection
55
61
  this.retryCount = 0;
56
- console.log(`Listening to topic: ${this.topic} with groupId: ${this.groupId}`);
62
+ console.log(`[${this.topic}] Listening to topic with groupId: ${this.groupId}`);
57
63
  yield this.consumer.run({
58
64
  eachMessage: (payload) => __awaiter(this, void 0, void 0, function* () {
59
65
  if (!payload.message.value)
@@ -78,27 +84,37 @@ class Listener {
78
84
  }
79
85
  })
80
86
  });
87
+ // Mark as successfully listening only after subscription and run are successful
88
+ this.isListening = true;
81
89
  }
82
90
  catch (error) {
91
+ // Reset listening flag on error so we can retry
92
+ this.isListening = false;
83
93
  // Handle connection/subscription errors gracefully
84
94
  // The "This server does not host this topic-partition" error is often harmless
85
95
  // and occurs when KafkaJS tries to list offsets for a topic that doesn't exist yet or has no messages
86
96
  if ((_a = error === null || error === void 0 ? void 0 : error.message) === null || _a === void 0 ? void 0 : _a.includes('does not host this topic-partition')) {
87
97
  this.retryCount++;
88
- if (this.retryCount <= this.maxRetries) {
89
- console.warn(`Topic partition error for ${this.topic} (attempt ${this.retryCount}/${this.maxRetries}):`, error.message);
90
- // Retry subscription after a delay (exponential backoff)
91
- const delay = Math.min(5000 * Math.pow(2, this.retryCount - 1), 30000);
92
- setTimeout(() => this.listen(), delay);
93
- return;
98
+ // Calculate exponential backoff delay (cap at maxRetryDelay)
99
+ const delay = Math.min(5000 * Math.pow(2, Math.min(this.retryCount - 1, 6)), this.maxRetryDelay);
100
+ // Show detailed logs for first few attempts, then less frequently
101
+ if (this.retryCount <= this.maxInitialRetries) {
102
+ console.warn(`[${this.topic}] Topic partition error (attempt ${this.retryCount}/${this.maxInitialRetries}): ${error.message}. Retrying in ${delay}ms...`);
94
103
  }
95
- else {
96
- console.error(`Max retries reached for topic ${this.topic}. Error:`, error.message);
97
- // Don't throw - just log and continue (service will still work for other topics)
98
- return;
104
+ else if (this.retryCount % 10 === 0) {
105
+ // Log every 10th retry after initial attempts to avoid log spam
106
+ console.warn(`[${this.topic}] Still retrying subscription (attempt ${this.retryCount}). Topic may not exist yet or has no data. Retrying in ${delay}ms...`);
99
107
  }
108
+ // Retry indefinitely with exponential backoff
109
+ // This allows the listener to connect once the topic becomes available
110
+ setTimeout(() => {
111
+ if (!this.isListening) {
112
+ this.listen();
113
+ }
114
+ }, delay);
115
+ return;
100
116
  }
101
- console.error(`Error setting up listener for topic: ${this.topic}`, error);
117
+ console.error(`[${this.topic}] Error setting up listener:`, error);
102
118
  throw error;
103
119
  }
104
120
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aichatwar/shared",
3
- "version": "1.0.103",
3
+ "version": "1.0.104",
4
4
  "main": "./build/index.js",
5
5
  "typs": "./build/index.d.ts",
6
6
  "files": [