@aichatwar/shared 1.0.122 → 1.0.124

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.
@@ -14,6 +14,6 @@ export declare abstract class Listener<T extends BaseEvent> {
14
14
  private crashHandlerSetup;
15
15
  constructor(consumer: Consumer);
16
16
  private setupCrashHandler;
17
- ack(): Promise<void>;
17
+ ack(payload?: EachMessagePayload): Promise<void>;
18
18
  listen(): Promise<void>;
19
19
  }
@@ -39,15 +39,17 @@ class Listener {
39
39
  this.crashHandlerSetup = true;
40
40
  }
41
41
  // Manual acknowledgment method
42
- ack() {
42
+ // Accepts optional payload for custom consumer patterns (e.g., realtime-gateway)
43
+ ack(payload) {
43
44
  return __awaiter(this, void 0, void 0, function* () {
44
- if (!this.currentPayload) {
45
- throw new Error('No current payload to acknowledge');
45
+ const targetPayload = payload || this.currentPayload;
46
+ if (!targetPayload) {
47
+ throw new Error('No current payload to acknowledge. Either set currentPayload or pass payload parameter.');
46
48
  }
47
49
  yield this.consumer.commitOffsets([{
48
- topic: this.currentPayload.topic,
49
- partition: this.currentPayload.partition,
50
- offset: (BigInt(this.currentPayload.message.offset) + BigInt(1)).toString()
50
+ topic: targetPayload.topic,
51
+ partition: targetPayload.partition,
52
+ offset: (BigInt(targetPayload.message.offset) + BigInt(1)).toString()
51
53
  }]);
52
54
  console.log(`Message manually acknowledged for topic: ${this.topic}`);
53
55
  });
@@ -76,21 +78,33 @@ class Listener {
76
78
  // Reset retry count on successful connection
77
79
  this.retryCount = 0;
78
80
  yield this.consumer.run({
81
+ // CRITICAL: Disable auto-commit to prevent message loss during rebalancing
82
+ // Offsets are only committed when we explicitly call ack()
83
+ autoCommit: false,
79
84
  eachMessage: (payload) => __awaiter(this, void 0, void 0, function* () {
80
- if (!payload.message.value)
85
+ if (!payload.message.value) {
86
+ // Acknowledge empty messages to avoid blocking
87
+ yield this.consumer.commitOffsets([{
88
+ topic: payload.topic,
89
+ partition: payload.partition,
90
+ offset: (BigInt(payload.message.offset) + BigInt(1)).toString()
91
+ }]);
81
92
  return;
82
- console.log(`Message received -> topic: ${this.topic}, groupId: ${this.groupId}`);
93
+ }
94
+ console.log(`Message received -> topic: ${this.topic}, groupId: ${this.groupId}, offset: ${payload.message.offset}`);
83
95
  // Store current payload for manual ack
84
96
  this.currentPayload = payload;
85
97
  try {
86
98
  const data = JSON.parse(payload.message.value.toString());
87
99
  yield this.onMessage(data, payload);
88
- // Note: Child listeners must call this.ack() manually after successful processing
89
- // If they don't call ack(), the message will be redelivered
100
+ // Note: Child listeners MUST call this.ack() manually after successful processing
101
+ // If they don't call ack(), the message will be redelivered after session timeout
102
+ // This ensures at-least-once delivery semantics
90
103
  }
91
104
  catch (error) {
92
- console.error(`Error processing message for topic: ${this.topic}`, error);
105
+ console.error(`Error processing message for topic: ${this.topic}, offset: ${payload.message.offset}`, error);
93
106
  // In case of error, we don't commit the offset, so the message will be redelivered
107
+ // This ensures failed messages are retried
94
108
  throw error;
95
109
  }
96
110
  finally {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aichatwar/shared",
3
- "version": "1.0.122",
3
+ "version": "1.0.124",
4
4
  "main": "./build/index.js",
5
5
  "typs": "./build/index.d.ts",
6
6
  "files": [