@seriousme/opifex 1.11.0 → 1.11.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.
Files changed (63) hide show
  1. package/README.md +5 -5
  2. package/benchmarks/bombing.ts +35 -0
  3. package/benchmarks/throughputCounter.ts +31 -0
  4. package/benchmarks/utils.ts +32 -0
  5. package/client/client.ts +6 -10
  6. package/client/context.ts +3 -9
  7. package/client/deps.ts +1 -2
  8. package/client/handlers/handlePublish.ts +2 -2
  9. package/client/handlers/handlePubrel.ts +1 -1
  10. package/deno/tcpServer.test.ts +0 -1
  11. package/dev_utils/dummyConn.ts +5 -5
  12. package/dev_utils/mod.ts +1 -0
  13. package/dev_utils/timers.ts +51 -0
  14. package/dist/client/client.d.ts +2 -6
  15. package/dist/client/client.d.ts.map +1 -1
  16. package/dist/client/client.js +6 -9
  17. package/dist/client/client.js.map +1 -1
  18. package/dist/client/context.d.ts +2 -3
  19. package/dist/client/context.d.ts.map +1 -1
  20. package/dist/client/context.js +4 -8
  21. package/dist/client/context.js.map +1 -1
  22. package/dist/client/deps.d.ts +1 -2
  23. package/dist/client/deps.d.ts.map +1 -1
  24. package/dist/client/deps.js +1 -2
  25. package/dist/client/deps.js.map +1 -1
  26. package/dist/client/handlers/handlePublish.js +2 -2
  27. package/dist/client/handlers/handlePublish.js.map +1 -1
  28. package/dist/client/handlers/handlePubrel.js +1 -1
  29. package/dist/client/handlers/handlePubrel.js.map +1 -1
  30. package/dist/mqttConn/mqttConn.d.ts +2 -7
  31. package/dist/mqttConn/mqttConn.d.ts.map +1 -1
  32. package/dist/mqttConn/mqttConn.js +18 -11
  33. package/dist/mqttConn/mqttConn.js.map +1 -1
  34. package/dist/utils/{asyncQueue.d.ts → BufferedAsyncIterable.d.ts} +8 -8
  35. package/dist/utils/BufferedAsyncIterable.d.ts.map +1 -0
  36. package/dist/utils/BufferedAsyncIterable.js +70 -0
  37. package/dist/utils/BufferedAsyncIterable.js.map +1 -0
  38. package/dist/utils/mod.d.ts +1 -2
  39. package/dist/utils/mod.d.ts.map +1 -1
  40. package/dist/utils/mod.js +1 -2
  41. package/dist/utils/mod.js.map +1 -1
  42. package/dist/utils/queue.d.ts +43 -0
  43. package/dist/utils/queue.d.ts.map +1 -0
  44. package/dist/utils/queue.js +63 -0
  45. package/dist/utils/queue.js.map +1 -0
  46. package/examples/tcpServer.test.ts +0 -1
  47. package/mqttConn/mqttConn.test.ts +5 -4
  48. package/mqttConn/mqttConn.ts +19 -15
  49. package/node/tcpServer.test.ts +0 -1
  50. package/package.json +1 -1
  51. package/server/test/handleConnect.test.ts +11 -8
  52. package/utils/BufferedAsyncIterable.ts +76 -0
  53. package/utils/mod.ts +1 -2
  54. package/utils/queue.ts +66 -0
  55. package/dist/utils/asyncQueue.d.ts.map +0 -1
  56. package/dist/utils/asyncQueue.js +0 -65
  57. package/dist/utils/asyncQueue.js.map +0 -1
  58. package/dist/utils/nextTick.d.ts +0 -17
  59. package/dist/utils/nextTick.d.ts.map +0 -1
  60. package/dist/utils/nextTick.js +0 -19
  61. package/dist/utils/nextTick.js.map +0 -1
  62. package/utils/asyncQueue.ts +0 -71
  63. package/utils/nextTick.ts +0 -18
package/utils/queue.ts ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * A simple queue implementation using an array.
3
+ * This implementation optimizes for O(1) enqueue and dequeue operations
4
+ * by avoiding array shifts, which are O(n).
5
+ *
6
+ * Usage:
7
+ * ```ts
8
+ * const queue = new ArrayQueue<number>();
9
+ * queue.enqueue(1);
10
+ * queue.enqueue(2);
11
+ * console.log(queue.dequeue()); // 1
12
+ * console.log(queue.size()); // 1
13
+ * console.log(queue.isEmpty()); // false
14
+ * queue.dequeue();
15
+ * console.log(queue.isEmpty()); // true
16
+ * ```
17
+ */
18
+
19
+ export class ArrayQueue<T> {
20
+ private items: T[] = [];
21
+ private headIndex: number = 0; // Tracks the front of the queue
22
+
23
+ /**
24
+ * size is the difference between the actual array length and the index offset
25
+ * @returns the number of items in the queue
26
+ */
27
+ public size(): number {
28
+ return this.items.length - this.headIndex;
29
+ }
30
+ /**
31
+ * isEmpty checks if the queue has no items
32
+ * @returns true if the queue is empty
33
+ */
34
+ public isEmpty(): boolean {
35
+ return this.size() === 0;
36
+ }
37
+ /**
38
+ * enqueue adds an item to the end of the queue
39
+ * O(1) - Push to the end is highly optimized in V8.
40
+ */
41
+ public enqueue(data: T): void {
42
+ this.items.push(data);
43
+ }
44
+ /**
45
+ * dequeue removes and returns the item at the front of the queue
46
+ * O(1) - Avoids array shifting by incrementing the index.
47
+ * @returns the item at the front of the queue or undefined if the queue is empty
48
+ */
49
+ public dequeue(): T | undefined {
50
+ if (this.isEmpty()) {
51
+ return undefined;
52
+ }
53
+
54
+ const item = this.items[this.headIndex];
55
+ this.headIndex++; // Move the "front" marker forward
56
+
57
+ // Optimization: Periodically "clean up" the dead space
58
+ // when the empty space (headIndex) exceeds a threshold.
59
+ // This amortizes the cost, keeping average time closer to O(1).
60
+ if (this.headIndex > 2000 && this.headIndex > this.items.length / 4) {
61
+ this.items = this.items.slice(this.headIndex);
62
+ this.headIndex = 0;
63
+ }
64
+ return item;
65
+ }
66
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"asyncQueue.d.ts","sourceRoot":"","sources":["../../utils/asyncQueue.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AAEH,qBAAa,UAAU,CAAC,CAAC;;IACvB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,cAAc,CAAY;IAElC,OAAO,CAAC,IAAI,CAAS;gBAIT,cAAc,CAAC,EAAE,MAAM;IAM7B,IAAI,IAAI,OAAO,CAAC,CAAC,CAAC;IAYxB,KAAK,CAAC,MAAM,SAAW,GAAG,IAAI;IAOvB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;IAM1E,IAAI,CAAC,IAAI,EAAE,CAAC;IAYZ,IAAI,MAAM,IAAI,OAAO,CAEpB;CACF"}
@@ -1,65 +0,0 @@
1
- import { Deferred } from "./deferred.js";
2
- import { nextTick } from "./nextTick.js";
3
- /**
4
- * An Async Queue is a queue that can be used to push items to it and then wait
5
- * for them to be consumed.
6
- *
7
- * @example
8
- * ```ts
9
- * const queue = new AsyncQueue<string>();
10
- * queue.push("hello");
11
- * for await (const item of queue) {
12
- * console.log(item); // "hello"
13
- * }
14
- * ```
15
- */
16
- export class AsyncQueue {
17
- queue = [];
18
- maxQueueLength = Infinity;
19
- done = false;
20
- #next;
21
- constructor(maxQueueLength) {
22
- if (maxQueueLength) {
23
- this.maxQueueLength = maxQueueLength;
24
- }
25
- }
26
- async next() {
27
- await nextTick();
28
- if (this.queue.length) {
29
- return Promise.resolve(this.queue.shift());
30
- }
31
- else if (this.done) {
32
- return Promise.reject("Closed");
33
- }
34
- else if (!this.#next) {
35
- this.#next = new Deferred();
36
- }
37
- return this.#next.promise;
38
- }
39
- close(reason = "closed") {
40
- this.done = true;
41
- if (this.#next) {
42
- this.#next.reject(new Error(reason));
43
- }
44
- }
45
- async *[Symbol.asyncIterator]() {
46
- while (true) {
47
- yield await this.next();
48
- }
49
- }
50
- push(item) {
51
- if (this.#next) {
52
- this.#next.resolve(item);
53
- this.#next = undefined;
54
- return;
55
- }
56
- if (this.queue.length > this.maxQueueLength) {
57
- this.queue.shift();
58
- }
59
- this.queue.push(item);
60
- }
61
- get isDone() {
62
- return this.done;
63
- }
64
- }
65
- //# sourceMappingURL=asyncQueue.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"asyncQueue.js","sourceRoot":"","sources":["../../utils/asyncQueue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC;;;;;;;;;;;;GAYG;AAEH,MAAM,OAAO,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,cAAc,GAAG,QAAQ,CAAC;IAE1B,IAAI,GAAG,KAAK,CAAC;IAErB,KAAK,CAAe;IAEpB,YAAY,cAAuB;QACjC,IAAI,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,cAAc,GAAG,cAAc,CAAC;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,MAAM,QAAQ,EAAE,CAAC;QACjB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YACtB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC,CAAC;QAC9C,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrB,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAClC,CAAC;aAAM,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,KAAK,GAAG,IAAI,QAAQ,EAAK,CAAC;QACjC,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,MAAM,GAAG,QAAQ;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC;QACvC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,IAAI,CAAC,IAAO;QACV,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -1,17 +0,0 @@
1
- /**
2
- * Returns a promise that resolves on the next tick of the Node.js event loop.
3
- * This is useful for deferring execution of code until after the current call stack is cleared.
4
- *
5
- * @example
6
- * ```ts
7
- * async function example() {
8
- * console.log('Before nextTick');
9
- * await nextTick();
10
- * console.log('After nextTick');
11
- * }
12
- * ```
13
- *
14
- * @returns {Promise<void>} A promise that resolves on the next tick of the event loop
15
- */
16
- export declare function nextTick(): Promise<void>;
17
- //# sourceMappingURL=nextTick.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nextTick.d.ts","sourceRoot":"","sources":["../../utils/nextTick.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAExC"}
@@ -1,19 +0,0 @@
1
- /**
2
- * Returns a promise that resolves on the next tick of the Node.js event loop.
3
- * This is useful for deferring execution of code until after the current call stack is cleared.
4
- *
5
- * @example
6
- * ```ts
7
- * async function example() {
8
- * console.log('Before nextTick');
9
- * await nextTick();
10
- * console.log('After nextTick');
11
- * }
12
- * ```
13
- *
14
- * @returns {Promise<void>} A promise that resolves on the next tick of the event loop
15
- */
16
- export function nextTick() {
17
- return new Promise((resolve) => setTimeout(resolve, 0));
18
- }
19
- //# sourceMappingURL=nextTick.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"nextTick.js","sourceRoot":"","sources":["../../utils/nextTick.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
@@ -1,71 +0,0 @@
1
- import { Deferred } from "./deferred.ts";
2
- import { nextTick } from "./nextTick.ts";
3
- /**
4
- * An Async Queue is a queue that can be used to push items to it and then wait
5
- * for them to be consumed.
6
- *
7
- * @example
8
- * ```ts
9
- * const queue = new AsyncQueue<string>();
10
- * queue.push("hello");
11
- * for await (const item of queue) {
12
- * console.log(item); // "hello"
13
- * }
14
- * ```
15
- */
16
-
17
- export class AsyncQueue<T> {
18
- private queue: T[] = [];
19
- private maxQueueLength = Infinity;
20
-
21
- private done = false;
22
-
23
- #next?: Deferred<T>;
24
-
25
- constructor(maxQueueLength?: number) {
26
- if (maxQueueLength) {
27
- this.maxQueueLength = maxQueueLength;
28
- }
29
- }
30
-
31
- async next(): Promise<T> {
32
- await nextTick();
33
- if (this.queue.length) {
34
- return Promise.resolve(this.queue.shift()!);
35
- } else if (this.done) {
36
- return Promise.reject("Closed");
37
- } else if (!this.#next) {
38
- this.#next = new Deferred<T>();
39
- }
40
- return this.#next.promise;
41
- }
42
-
43
- close(reason = "closed"): void {
44
- this.done = true;
45
- if (this.#next) {
46
- this.#next.reject(new Error(reason));
47
- }
48
- }
49
-
50
- async *[Symbol.asyncIterator](): AsyncGenerator<Awaited<T>, void, unknown> {
51
- while (true) {
52
- yield await this.next();
53
- }
54
- }
55
-
56
- push(item: T) {
57
- if (this.#next) {
58
- this.#next.resolve(item);
59
- this.#next = undefined;
60
- return;
61
- }
62
- if (this.queue.length > this.maxQueueLength) {
63
- this.queue.shift();
64
- }
65
- this.queue.push(item);
66
- }
67
-
68
- get isDone(): boolean {
69
- return this.done;
70
- }
71
- }
package/utils/nextTick.ts DELETED
@@ -1,18 +0,0 @@
1
- /**
2
- * Returns a promise that resolves on the next tick of the Node.js event loop.
3
- * This is useful for deferring execution of code until after the current call stack is cleared.
4
- *
5
- * @example
6
- * ```ts
7
- * async function example() {
8
- * console.log('Before nextTick');
9
- * await nextTick();
10
- * console.log('After nextTick');
11
- * }
12
- * ```
13
- *
14
- * @returns {Promise<void>} A promise that resolves on the next tick of the event loop
15
- */
16
- export function nextTick(): Promise<void> {
17
- return new Promise((resolve) => setTimeout(resolve, 0));
18
- }