cojson 0.12.0 → 0.12.1

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,4 +1,4 @@
1
1
 
2
- > cojson@0.12.0 build /home/runner/_work/jazz/jazz/packages/cojson
2
+ > cojson@0.12.1 build /home/runner/_work/jazz/jazz/packages/cojson
3
3
  > rm -rf ./dist && tsc --sourceMap --outDir dist
4
4
 
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # cojson
2
2
 
3
+ ## 0.12.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 5a00fe0: Re-introducing linked lists on PriorityBasedMessageQueue
8
+
3
9
  ## 0.12.0
4
10
 
5
11
  ### Minor Changes
@@ -6,6 +6,21 @@ export type QueueEntry = {
6
6
  resolve: () => void;
7
7
  reject: (_: unknown) => void;
8
8
  };
9
+ type LinkedListNode<T> = {
10
+ value: T;
11
+ next: LinkedListNode<T> | undefined;
12
+ };
13
+ /**
14
+ * Using a linked list to make the shift operation O(1) instead of O(n)
15
+ * as our queues can grow very large when the system is under pressure.
16
+ */
17
+ export declare class LinkedList<T> {
18
+ head: LinkedListNode<T> | undefined;
19
+ tail: LinkedListNode<T> | undefined;
20
+ length: number;
21
+ push(value: T): void;
22
+ shift(): T | undefined;
23
+ }
9
24
  export declare class PriorityBasedMessageQueue {
10
25
  private defaultPriority;
11
26
  private queues;
@@ -15,4 +30,5 @@ export declare class PriorityBasedMessageQueue {
15
30
  push(msg: SyncMessage): Promise<void>;
16
31
  pull(): QueueEntry | undefined;
17
32
  }
33
+ export {};
18
34
  //# sourceMappingURL=PriorityBasedMessageQueue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PriorityBasedMessageQueue.d.ts","sourceRoot":"","sources":["../src/PriorityBasedMessageQueue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAkB7C,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,WAAW,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9B,CAAC;AAYF,qBAAa,yBAAyB;IAcxB,OAAO,CAAC,eAAe;IAbnC,OAAO,CAAC,MAAM,CAAgD;IAC9D,gBAAgB,sFAMX;IAEL,OAAO,CAAC,QAAQ;gBAII,eAAe,EAAE,eAAe;IAE7C,IAAI,CAAC,GAAG,EAAE,WAAW;IAerB,IAAI;CAaZ"}
1
+ {"version":3,"file":"PriorityBasedMessageQueue.d.ts","sourceRoot":"","sources":["../src/PriorityBasedMessageQueue.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAkB7C,MAAM,MAAM,UAAU,GAAG;IACvB,GAAG,EAAE,WAAW,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9B,CAAC;AAaF,KAAK,cAAc,CAAC,CAAC,IAAI;IACvB,KAAK,EAAE,CAAC,CAAC;IACT,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;CACrC,CAAC;AAEF;;;GAGG;AACH,qBAAa,UAAU,CAAC,CAAC;IACvB,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAa;IAChD,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAa;IAChD,MAAM,SAAK;IAEX,IAAI,CAAC,KAAK,EAAE,CAAC;IAgBb,KAAK;CAkBN;AAED,qBAAa,yBAAyB;IAuBxB,OAAO,CAAC,eAAe;IAtBnC,OAAO,CAAC,MAAM,CASZ;IACF,gBAAgB,sFAMX;IAEL,OAAO,CAAC,QAAQ;gBAII,eAAe,EAAE,eAAe;IAE7C,IAAI,CAAC,GAAG,EAAE,WAAW;IAerB,IAAI;CAaZ"}
@@ -12,13 +12,62 @@ function promiseWithResolvers() {
12
12
  reject,
13
13
  };
14
14
  }
15
+ /**
16
+ * Using a linked list to make the shift operation O(1) instead of O(n)
17
+ * as our queues can grow very large when the system is under pressure.
18
+ */
19
+ export class LinkedList {
20
+ constructor() {
21
+ this.head = undefined;
22
+ this.tail = undefined;
23
+ this.length = 0;
24
+ }
25
+ push(value) {
26
+ const node = { value, next: undefined };
27
+ if (this.head === undefined) {
28
+ this.head = node;
29
+ this.tail = node;
30
+ }
31
+ else if (this.tail) {
32
+ this.tail.next = node;
33
+ this.tail = node;
34
+ }
35
+ else {
36
+ throw new Error("LinkedList is corrupted");
37
+ }
38
+ this.length++;
39
+ }
40
+ shift() {
41
+ if (!this.head) {
42
+ return undefined;
43
+ }
44
+ const node = this.head;
45
+ const value = node.value;
46
+ this.head = node.next;
47
+ node.next = undefined;
48
+ if (this.head === undefined) {
49
+ this.tail = undefined;
50
+ }
51
+ this.length--;
52
+ return value;
53
+ }
54
+ }
15
55
  export class PriorityBasedMessageQueue {
16
56
  getQueue(priority) {
17
57
  return this.queues[priority];
18
58
  }
19
59
  constructor(defaultPriority) {
20
60
  this.defaultPriority = defaultPriority;
21
- this.queues = [[], [], [], [], [], [], [], []];
61
+ this.queues = [
62
+ new LinkedList(),
63
+ new LinkedList(),
64
+ new LinkedList(),
65
+ new LinkedList(),
66
+ new LinkedList(),
67
+ new LinkedList(),
68
+ new LinkedList(),
69
+ new LinkedList(),
70
+ ];
22
71
  this.queueSizeCounter = metrics
23
72
  .getMeter("cojson")
24
73
  .createUpDownCounter("jazz.messagequeue.size", {
@@ -1 +1 @@
1
- {"version":3,"file":"PriorityBasedMessageQueue.js","sourceRoot":"","sources":["../src/PriorityBasedMessageQueue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAIxD,SAAS,oBAAoB;IAC3B,IAAI,OAAO,GAAG,CAAC,CAAI,EAAE,EAAE,GAAE,CAAC,CAAC;IAC3B,IAAI,MAAM,GAAG,CAAC,CAAU,EAAE,EAAE,GAAE,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE;QACnD,OAAO,GAAG,QAAQ,CAAC;QACnB,MAAM,GAAG,OAAO,CAAC;IACnB,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,OAAO;QACP,OAAO;QACP,MAAM;KACP,CAAC;AACJ,CAAC;AAmBD,MAAM,OAAO,yBAAyB;IAU5B,QAAQ,CAAC,QAAyB;QACxC,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/B,CAAC;IAED,YAAoB,eAAgC;QAAhC,oBAAe,GAAf,eAAe,CAAiB;QAb5C,WAAM,GAAe,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,qBAAgB,GAAG,OAAO;aACvB,QAAQ,CAAC,QAAQ,CAAC;aAClB,mBAAmB,CAAC,wBAAwB,EAAE;YAC7C,WAAW,EAAE,2BAA2B;YACxC,SAAS,EAAE,SAAS,CAAC,GAAG;YACxB,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;IAMkD,CAAC;IAEjD,IAAI,CAAC,GAAgB;QAC1B,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,oBAAoB,EAAQ,CAAC;QAClE,MAAM,KAAK,GAAe,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;QAE5D,MAAM,QAAQ,GAAG,UAAU,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC;QAEzE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAEpC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,EAAE;YAC3B,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAEM,IAAI;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEpE,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;YAC5B,QAAQ;SACT,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IACxC,CAAC;CACF"}
1
+ {"version":3,"file":"PriorityBasedMessageQueue.js","sourceRoot":"","sources":["../src/PriorityBasedMessageQueue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=LinkedList.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedList.test.d.ts","sourceRoot":"","sources":["../../src/tests/LinkedList.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ import { beforeEach, describe, expect, it } from "vitest";
2
+ import { LinkedList } from "../PriorityBasedMessageQueue";
3
+ describe("LinkedList", () => {
4
+ let list;
5
+ beforeEach(() => {
6
+ list = new LinkedList();
7
+ });
8
+ describe("initialization", () => {
9
+ it("should create an empty list", () => {
10
+ expect(list.length).toBe(0);
11
+ expect(list.head).toBeUndefined();
12
+ expect(list.tail).toBeUndefined();
13
+ });
14
+ });
15
+ describe("push", () => {
16
+ it("should add an element to an empty list", () => {
17
+ list.push(1);
18
+ expect(list.length).toBe(1);
19
+ expect(list.head?.value).toBe(1);
20
+ expect(list.tail?.value).toBe(1);
21
+ });
22
+ it("should add multiple elements in sequence", () => {
23
+ list.push(1);
24
+ list.push(2);
25
+ list.push(3);
26
+ expect(list.length).toBe(3);
27
+ expect(list.head?.value).toBe(1);
28
+ expect(list.tail?.value).toBe(3);
29
+ });
30
+ });
31
+ describe("shift", () => {
32
+ it("should return undefined for empty list", () => {
33
+ expect(list.shift()).toBeUndefined();
34
+ expect(list.length).toBe(0);
35
+ expect(list.head).toBeUndefined();
36
+ expect(list.tail).toBeUndefined();
37
+ });
38
+ it("should remove and return the first element", () => {
39
+ list.push(1);
40
+ list.push(2);
41
+ const shifted = list.shift();
42
+ expect(shifted).toBe(1);
43
+ expect(list.length).toBe(1);
44
+ expect(list.head?.value).toBe(2);
45
+ expect(list.tail?.value).toBe(2);
46
+ });
47
+ it("should maintain correct order when shifting multiple times", () => {
48
+ list.push(1);
49
+ list.push(2);
50
+ list.push(3);
51
+ expect(list.shift()).toBe(1);
52
+ expect(list.shift()).toBe(2);
53
+ expect(list.shift()).toBe(3);
54
+ expect(list.length).toBe(0);
55
+ expect(list.head).toBeUndefined();
56
+ expect(list.tail).toBeUndefined();
57
+ });
58
+ it("should handle shift after last element is removed", () => {
59
+ list.push(1);
60
+ list.shift();
61
+ expect(list.shift()).toBeUndefined();
62
+ expect(list.length).toBe(0);
63
+ expect(list.head).toBeUndefined();
64
+ expect(list.tail).toBeUndefined();
65
+ });
66
+ });
67
+ describe("edge cases", () => {
68
+ it("should handle push after all elements have been shifted", () => {
69
+ list.push(1);
70
+ list.shift();
71
+ list.push(2);
72
+ expect(list.length).toBe(1);
73
+ expect(list.shift()).toBe(2);
74
+ });
75
+ it("should handle alternating push and shift operations", () => {
76
+ list.push(1);
77
+ expect(list.shift()).toBe(1);
78
+ list.push(2);
79
+ expect(list.shift()).toBe(2);
80
+ expect(list.length).toBe(0);
81
+ });
82
+ });
83
+ });
84
+ //# sourceMappingURL=LinkedList.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedList.test.js","sourceRoot":"","sources":["../../src/tests/LinkedList.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "type": "module",
27
27
  "license": "MIT",
28
- "version": "0.12.0",
28
+ "version": "0.12.1",
29
29
  "devDependencies": {
30
30
  "@opentelemetry/sdk-metrics": "^2.0.0",
31
31
  "typescript": "~5.6.2",
@@ -33,10 +33,70 @@ type Tuple<T, N extends number, A extends unknown[] = []> = A extends {
33
33
  }
34
34
  ? A
35
35
  : Tuple<T, N, [...A, T]>;
36
- type QueueTuple = Tuple<QueueEntry[], 8>;
36
+
37
+ type QueueTuple = Tuple<LinkedList<QueueEntry>, 8>;
38
+
39
+ type LinkedListNode<T> = {
40
+ value: T;
41
+ next: LinkedListNode<T> | undefined;
42
+ };
43
+
44
+ /**
45
+ * Using a linked list to make the shift operation O(1) instead of O(n)
46
+ * as our queues can grow very large when the system is under pressure.
47
+ */
48
+ export class LinkedList<T> {
49
+ head: LinkedListNode<T> | undefined = undefined;
50
+ tail: LinkedListNode<T> | undefined = undefined;
51
+ length = 0;
52
+
53
+ push(value: T) {
54
+ const node = { value, next: undefined };
55
+
56
+ if (this.head === undefined) {
57
+ this.head = node;
58
+ this.tail = node;
59
+ } else if (this.tail) {
60
+ this.tail.next = node;
61
+ this.tail = node;
62
+ } else {
63
+ throw new Error("LinkedList is corrupted");
64
+ }
65
+
66
+ this.length++;
67
+ }
68
+
69
+ shift() {
70
+ if (!this.head) {
71
+ return undefined;
72
+ }
73
+
74
+ const node = this.head;
75
+ const value = node.value;
76
+ this.head = node.next;
77
+ node.next = undefined;
78
+
79
+ if (this.head === undefined) {
80
+ this.tail = undefined;
81
+ }
82
+
83
+ this.length--;
84
+
85
+ return value;
86
+ }
87
+ }
37
88
 
38
89
  export class PriorityBasedMessageQueue {
39
- private queues: QueueTuple = [[], [], [], [], [], [], [], []];
90
+ private queues: QueueTuple = [
91
+ new LinkedList<QueueEntry>(),
92
+ new LinkedList<QueueEntry>(),
93
+ new LinkedList<QueueEntry>(),
94
+ new LinkedList<QueueEntry>(),
95
+ new LinkedList<QueueEntry>(),
96
+ new LinkedList<QueueEntry>(),
97
+ new LinkedList<QueueEntry>(),
98
+ new LinkedList<QueueEntry>(),
99
+ ];
40
100
  queueSizeCounter = metrics
41
101
  .getMeter("cojson")
42
102
  .createUpDownCounter("jazz.messagequeue.size", {
@@ -0,0 +1,96 @@
1
+ import { beforeEach, describe, expect, it } from "vitest";
2
+ import { LinkedList } from "../PriorityBasedMessageQueue";
3
+
4
+ describe("LinkedList", () => {
5
+ let list: LinkedList<number>;
6
+
7
+ beforeEach(() => {
8
+ list = new LinkedList<number>();
9
+ });
10
+
11
+ describe("initialization", () => {
12
+ it("should create an empty list", () => {
13
+ expect(list.length).toBe(0);
14
+ expect(list.head).toBeUndefined();
15
+ expect(list.tail).toBeUndefined();
16
+ });
17
+ });
18
+
19
+ describe("push", () => {
20
+ it("should add an element to an empty list", () => {
21
+ list.push(1);
22
+ expect(list.length).toBe(1);
23
+ expect(list.head?.value).toBe(1);
24
+ expect(list.tail?.value).toBe(1);
25
+ });
26
+
27
+ it("should add multiple elements in sequence", () => {
28
+ list.push(1);
29
+ list.push(2);
30
+ list.push(3);
31
+ expect(list.length).toBe(3);
32
+ expect(list.head?.value).toBe(1);
33
+ expect(list.tail?.value).toBe(3);
34
+ });
35
+ });
36
+
37
+ describe("shift", () => {
38
+ it("should return undefined for empty list", () => {
39
+ expect(list.shift()).toBeUndefined();
40
+ expect(list.length).toBe(0);
41
+ expect(list.head).toBeUndefined();
42
+ expect(list.tail).toBeUndefined();
43
+ });
44
+
45
+ it("should remove and return the first element", () => {
46
+ list.push(1);
47
+ list.push(2);
48
+
49
+ const shifted = list.shift();
50
+ expect(shifted).toBe(1);
51
+ expect(list.length).toBe(1);
52
+ expect(list.head?.value).toBe(2);
53
+ expect(list.tail?.value).toBe(2);
54
+ });
55
+
56
+ it("should maintain correct order when shifting multiple times", () => {
57
+ list.push(1);
58
+ list.push(2);
59
+ list.push(3);
60
+
61
+ expect(list.shift()).toBe(1);
62
+ expect(list.shift()).toBe(2);
63
+ expect(list.shift()).toBe(3);
64
+ expect(list.length).toBe(0);
65
+ expect(list.head).toBeUndefined();
66
+ expect(list.tail).toBeUndefined();
67
+ });
68
+
69
+ it("should handle shift after last element is removed", () => {
70
+ list.push(1);
71
+ list.shift();
72
+ expect(list.shift()).toBeUndefined();
73
+ expect(list.length).toBe(0);
74
+ expect(list.head).toBeUndefined();
75
+ expect(list.tail).toBeUndefined();
76
+ });
77
+ });
78
+
79
+ describe("edge cases", () => {
80
+ it("should handle push after all elements have been shifted", () => {
81
+ list.push(1);
82
+ list.shift();
83
+ list.push(2);
84
+ expect(list.length).toBe(1);
85
+ expect(list.shift()).toBe(2);
86
+ });
87
+
88
+ it("should handle alternating push and shift operations", () => {
89
+ list.push(1);
90
+ expect(list.shift()).toBe(1);
91
+ list.push(2);
92
+ expect(list.shift()).toBe(2);
93
+ expect(list.length).toBe(0);
94
+ });
95
+ });
96
+ });