@riocrypto/common 1.0.2554 → 1.0.2555

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.
@@ -11,9 +11,12 @@ export declare abstract class Listener<T extends Event> {
11
11
  abstract onMessage(data: T["data"], msg: Message): void;
12
12
  private client;
13
13
  protected ackWait: number;
14
+ private processedSequences;
15
+ private static readonly MAX_TRACKED_SEQUENCES;
14
16
  constructor(client: Stan);
15
17
  subscriptionOptions(): import("node-nats-streaming").SubscriptionOptions;
16
18
  listen(): void;
19
+ private trackSequence;
17
20
  parseMessage(msg: Message): any;
18
21
  }
19
22
  export {};
@@ -4,8 +4,9 @@ exports.Listener = void 0;
4
4
  class Listener {
5
5
  constructor(client) {
6
6
  this.ackWait = 5 * 1000;
7
+ this.processedSequences = new Set();
7
8
  this.client = client;
8
- this.listenerStartTime = new Date(); // Record the start time of the listener
9
+ this.listenerStartTime = new Date();
9
10
  }
10
11
  subscriptionOptions() {
11
12
  return this.client
@@ -18,21 +19,36 @@ class Listener {
18
19
  const subscription = this.client.subscribe(this.subject, this.queueGroupName, this.subscriptionOptions());
19
20
  subscription.on("message", (msg) => {
20
21
  console.log(`Message received: ${this.subject} / ${this.queueGroupName}`);
21
- if (msg.getTimestamp() >= this.listenerStartTime) {
22
- // Always ack the message to avoid duplicate processing loops caused by forgetting to ack the message
22
+ const sequence = msg.getSequence();
23
+ if (msg.getTimestamp() < this.listenerStartTime) {
24
+ console.log("Ignoring old message");
23
25
  msg.ack();
24
- const parsedMessage = this.parseMessage(msg);
25
- this.onMessage(parsedMessage, msg);
26
+ return;
26
27
  }
27
- else {
28
- console.log("Ignoring old message");
28
+ if (msg.isRedelivered() || this.processedSequences.has(sequence)) {
29
+ console.log(`Skipping redelivered/duplicate message seq=${sequence} on ${this.subject}/${this.queueGroupName}`);
29
30
  msg.ack();
31
+ return;
30
32
  }
33
+ this.trackSequence(sequence);
34
+ msg.ack();
35
+ const parsedMessage = this.parseMessage(msg);
36
+ this.onMessage(parsedMessage, msg);
31
37
  });
32
38
  }
39
+ trackSequence(sequence) {
40
+ this.processedSequences.add(sequence);
41
+ if (this.processedSequences.size > Listener.MAX_TRACKED_SEQUENCES) {
42
+ const oldest = this.processedSequences.values().next().value;
43
+ if (oldest !== undefined) {
44
+ this.processedSequences.delete(oldest);
45
+ }
46
+ }
47
+ }
33
48
  parseMessage(msg) {
34
49
  const data = msg.getData();
35
50
  return typeof data === "string" ? JSON.parse(data) : data;
36
51
  }
37
52
  }
38
53
  exports.Listener = Listener;
54
+ Listener.MAX_TRACKED_SEQUENCES = 10000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@riocrypto/common",
3
- "version": "1.0.2554",
3
+ "version": "1.0.2555",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",