@seriousme/opifex 1.11.0 → 1.11.2

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 (71) hide show
  1. package/README.md +5 -5
  2. package/benchmarks/receiver.ts +35 -0
  3. package/benchmarks/sender.ts +32 -0
  4. package/benchmarks/utils.ts +9 -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/server/handlers/handlePublish.d.ts.map +1 -1
  35. package/dist/server/handlers/handlePublish.js +17 -2
  36. package/dist/server/handlers/handlePublish.js.map +1 -1
  37. package/dist/server/handlers/handlePubrel.d.ts.map +1 -1
  38. package/dist/server/handlers/handlePubrel.js +6 -10
  39. package/dist/server/handlers/handlePubrel.js.map +1 -1
  40. package/dist/utils/{asyncQueue.d.ts → BufferedAsyncIterable.d.ts} +8 -8
  41. package/dist/utils/BufferedAsyncIterable.d.ts.map +1 -0
  42. package/dist/utils/BufferedAsyncIterable.js +70 -0
  43. package/dist/utils/BufferedAsyncIterable.js.map +1 -0
  44. package/dist/utils/mod.d.ts +1 -2
  45. package/dist/utils/mod.d.ts.map +1 -1
  46. package/dist/utils/mod.js +1 -2
  47. package/dist/utils/mod.js.map +1 -1
  48. package/dist/utils/queue.d.ts +43 -0
  49. package/dist/utils/queue.d.ts.map +1 -0
  50. package/dist/utils/queue.js +63 -0
  51. package/dist/utils/queue.js.map +1 -0
  52. package/examples/tcpServer.test.ts +0 -1
  53. package/mqttConn/mqttConn.test.ts +5 -4
  54. package/mqttConn/mqttConn.ts +19 -15
  55. package/node/tcpServer.test.ts +0 -1
  56. package/package.json +1 -1
  57. package/server/handlers/handlePublish.ts +18 -2
  58. package/server/handlers/handlePubrel.ts +6 -10
  59. package/server/test/handleConnect.test.ts +11 -8
  60. package/utils/BufferedAsyncIterable.ts +76 -0
  61. package/utils/mod.ts +1 -2
  62. package/utils/queue.ts +66 -0
  63. package/dist/utils/asyncQueue.d.ts.map +0 -1
  64. package/dist/utils/asyncQueue.js +0 -65
  65. package/dist/utils/asyncQueue.js.map +0 -1
  66. package/dist/utils/nextTick.d.ts +0 -17
  67. package/dist/utils/nextTick.d.ts.map +0 -1
  68. package/dist/utils/nextTick.js +0 -19
  69. package/dist/utils/nextTick.js.map +0 -1
  70. package/utils/asyncQueue.ts +0 -71
  71. package/utils/nextTick.ts +0 -18
@@ -22,8 +22,6 @@ export interface IMqttConn extends AsyncIterable<AnyPacket> {
22
22
  readonly isClosed: boolean;
23
23
  /** Reason for connection closure if any */
24
24
  readonly reason: string | undefined;
25
- /** Async iterator for receiving packets */
26
- [Symbol.asyncIterator](): AsyncIterableIterator<AnyPacket>;
27
25
  /** Send an MQTT packet */
28
26
  send(data: AnyPacket): Promise<void>;
29
27
  /** Close the connection */
@@ -41,6 +39,7 @@ export declare function readPacket(conn: Conn, codecOpts: CodecOpts): Promise<An
41
39
  * MQTT Connection class implementing IMqttConn interface
42
40
  */
43
41
  export declare class MqttConn implements IMqttConn {
42
+ #private;
44
43
  /** Underlying connection */
45
44
  readonly conn: Conn;
46
45
  /** codecOpts */
@@ -66,11 +65,7 @@ export declare class MqttConn implements IMqttConn {
66
65
  get reason(): string | undefined;
67
66
  /** Get remoteAdress */
68
67
  get remoteAddress(): string;
69
- /**
70
- * Async iterator for receiving packets
71
- * @yields MQTT packets
72
- */
73
- [Symbol.asyncIterator](): AsyncIterableIterator<AnyPacket>;
68
+ [Symbol.asyncIterator](): AsyncIterator<AnyPacket>;
74
69
  /**
75
70
  * Send an MQTT packet
76
71
  * @param data Packet to send
@@ -1 +1 @@
1
- {"version":3,"file":"mqttConn.d.ts","sourceRoot":"","sources":["../../mqttConn/mqttConn.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EAET,aAAa,EACd,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAIX;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,aAAa,CAAC,SAAS,CAAC;IACzD,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,2CAA2C;IAC3C,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,SAAS,CAAC,CAAC;IAC3D,0BAA0B;IAC1B,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,2BAA2B;IAC3B,KAAK,IAAI,IAAI,CAAC;CACf;AAgCD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,SAAS,CAAC,CAuBpB;AAED;;GAEG;AACH,qBAAa,QAAS,YAAW,SAAS;IACxC,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,2CAA2C;IAC3C,OAAO,CAAC,OAAO,CAAiC;IAChD,mCAAmC;IACnC,OAAO,CAAC,SAAS,CAAS;IAE1B;;;;;;;OAOG;gBACS,EACV,IAAI,EACJ,qBAA8C,EAC9C,aAAiC,GAClC,EAAE;QACD,IAAI,EAAE,QAAQ,CAAC;QACf,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B;IASD,wCAAwC;IACxC,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,CAE/B;IAED,uBAAuB;IACvB,IAAI,aAAa,IAAI,MAAM,CAK1B;IAED;;;OAGG;IACI,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,SAAS,CAAC;IAqBjE;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1C,mCAAmC;IACnC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,2BAA2B;IAC3B,KAAK,IAAI,IAAI;CAUd"}
1
+ {"version":3,"file":"mqttConn.d.ts","sourceRoot":"","sources":["../../mqttConn/mqttConn.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EAET,aAAa,EACd,MAAM,sBAAsB,CAAC;AAU9B,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;GAEG;AACH,eAAO,MAAM,aAAa;;;;CAIhB,CAAC;AAIX;;GAEG;AACH,MAAM,WAAW,SAAU,SAAQ,aAAa,CAAC,SAAS,CAAC;IACzD,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,0BAA0B;IAC1B,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,2BAA2B;IAC3B,KAAK,IAAI,IAAI,CAAC;CACf;AAgCD;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,SAAS,CAAC,CAuBpB;AAED;;GAEG;AACH,qBAAa,QAAS,YAAW,SAAS;;IACxC,4BAA4B;IAC5B,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,gBAAgB;IAChB,SAAS,EAAE,SAAS,CAAC;IACrB,2CAA2C;IAC3C,OAAO,CAAC,OAAO,CAAiC;IAChD,mCAAmC;IACnC,OAAO,CAAC,SAAS,CAAS;IAE1B;;;;;;;OAOG;gBACS,EACV,IAAI,EACJ,qBAA8C,EAC9C,aAAiC,GAClC,EAAE;QACD,IAAI,EAAE,QAAQ,CAAC;QACf,qBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,aAAa,CAAC,EAAE,aAAa,CAAC;KAC/B;IASD,wCAAwC;IACxC,IAAI,MAAM,IAAI,MAAM,GAAG,SAAS,CAE/B;IAED,uBAAuB;IACvB,IAAI,aAAa,IAAI,MAAM,CAK1B;IA0BM,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,SAAS,CAAC;IAOzD;;;OAGG;IACG,IAAI,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1C,mCAAmC;IACnC,IAAI,QAAQ,IAAI,OAAO,CAEtB;IAED,2BAA2B;IAC3B,KAAK,IAAI,IAAI;CAUd"}
@@ -108,25 +108,32 @@ export class MqttConn {
108
108
  return "unknown";
109
109
  }
110
110
  /**
111
- * Async iterator for receiving packets
112
- * @yields MQTT packets
111
+ * Returns incoming MQTT packages until the connection is closed. Note that
112
+ * the connection will close automatically upon receiving an invalid packet.
113
+ *
114
+ * @returns a Promise that resolves to AnyPacket if the connection is open
115
+ * and working nominally, undefined otherwise.
113
116
  */
114
- async *[Symbol.asyncIterator]() {
115
- while (!this._isClosed) {
116
- try {
117
- yield await readPacket(this.conn, this.codecOpts);
118
- }
119
- catch (err) {
117
+ #receive() {
118
+ if (!this._isClosed) {
119
+ return readPacket(this.conn, this.codecOpts).catch((err) => {
120
120
  if (err instanceof Error) {
121
121
  if (err.name === "PartialReadError") {
122
122
  err.message = MqttConnError.UnexpectedEof;
123
123
  }
124
124
  this._reason = err.message;
125
125
  }
126
- // packet too large, malformed packet or connection closed
126
+ // packet too large, malformed packet or connection closed.
127
127
  this.close();
128
- break;
129
- }
128
+ return undefined;
129
+ });
130
+ }
131
+ return Promise.resolve(undefined);
132
+ }
133
+ async *[Symbol.asyncIterator]() {
134
+ let packet;
135
+ while ((packet = await this.#receive()) !== undefined) {
136
+ yield packet;
130
137
  }
131
138
  }
132
139
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"mqttConn.js","sourceRoot":"","sources":["../../mqttConn/mqttConn.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,EACL,aAAa,EACb,MAAM,EACN,gBAAgB,EAChB,SAAS,GACV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B,aAAa,EAAE,gBAAgB;IAC/B,cAAc,EAAE,kBAAkB;IAClC,aAAa,EAAE,gBAAgB;CACvB,CAAC;AAEX,MAAM,sBAAsB,GAAG,CAAC,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,MAAM;AAoBtD;;;;;GAKG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAU;IAChC,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACxD,MAAM,CAAC,SAAS,KAAK,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACrD,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,QAAQ,CAAC,IAAU,EAAE,GAAe;IACjD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,OAAO,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,IAAI,KAAK,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;QAChD,SAAS,IAAI,IAAI,CAAC;IACpB,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAU,EACV,SAAoB;IAEpB,yCAAyC;IACzC,wDAAwD;IACxD,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;IACxC,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IACvC,IAAI,MAA2B,CAAC;IAChC,GAAG,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE;IAEvB,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,MAAM,qBAAqB,GAAG,SAAS,CAAC,qBAAqB,CAAC;IAC9D,MAAM,CACJ,eAAe,GAAG,qBAAqB,GAAG,CAAC,EAC3C,aAAa,CAAC,cAAc,CAC7B,CAAC;IACF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,eAAe,CAAC,CAAC;IAClD,8BAA8B;IAC9B,MAAM,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;IAChC,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC9D,MAAM,CAAC,MAAM,KAAK,IAAI,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IACrD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,QAAQ;IACnB,4BAA4B;IACnB,IAAI,CAAO;IACpB,gBAAgB;IAChB,SAAS,CAAY;IACrB,2CAA2C;IACnC,OAAO,GAAuB,SAAS,CAAC;IAChD,mCAAmC;IAC3B,SAAS,GAAG,KAAK,CAAC;IAE1B;;;;;;;OAOG;IACH,YAAY,EACV,IAAI,EACJ,qBAAqB,GAAG,sBAAsB,EAC9C,aAAa,GAAG,SAAS,CAAC,OAAO,GAKlC;QACC,IAAI,CAAC,IAAI,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG;YACf,qBAAqB;YACrB,qBAAqB,EAAE,qBAAqB;YAC5C,aAAa;SACd,CAAC;IACJ,CAAC;IAED,wCAAwC;IACxC,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,uBAAuB;IACvB,IAAI,aAAa;QACf,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,KAAK,KAAK,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;QACvC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,MAAM,MAAM,UAAU,CACpB,IAAI,CAAC,IAAI,EACT,IAAI,CAAC,SAAS,CACf,CAAC;YACJ,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;oBACzB,IAAI,GAAG,CAAC,IAAI,KAAK,kBAAkB,EAAE,CAAC;wBACpC,GAAG,CAAC,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC;oBAC5C,CAAC;oBACD,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;gBAC7B,CAAC;gBACD,0DAA0D;gBAC1D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACb,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,IAAI,CAAC,IAAe;QACxB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC;YAC7B,CAAC;YACD,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,2BAA2B;IAC3B,KAAK;QACH,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAC1B,IAAI,CAAC;YACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"mqttConn.js","sourceRoot":"","sources":["../../mqttConn/mqttConn.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"handlePublish.d.ts","sourceRoot":"","sources":["../../../server/handlers/handlePublish.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAS,MAAM,YAAY,CAAC;AAkBvD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAiCf"}
1
+ {"version":3,"file":"handlePublish.d.ts","sourceRoot":"","sources":["../../../server/handlers/handlePublish.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAS,MAAM,YAAY,CAAC;AAkBvD;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,IAAI,CAAC,CAiDf"}
@@ -43,9 +43,24 @@ export async function handlePublish(ctx, packet) {
43
43
  });
44
44
  return;
45
45
  }
46
- // qos 2
46
+ /*
47
+ In the QoS 2 delivery protocol, the Receiver
48
+
49
+ - MUST respond with a PUBREC containing the Packet Identifier from the incoming PUBLISH Packet,
50
+ having accepted ownership of the Application Message.
51
+ - Until it has received the corresponding PUBREL packet, the Receiver MUST acknowledge any subsequent
52
+ PUBLISH packet with the same Packet Identifier by sending a PUBREC. It MUST NOT cause duplicate
53
+ messages to be delivered to any onward recipients in this case.
54
+ - MUST respond to a PUBREL packet by sending a PUBCOMP packet containing the same Packet Identifier as the PUBREL.
55
+ - After it has sent a PUBCOMP, the receiver MUST treat any subsequent PUBLISH packet that contains that Packet
56
+ Identifier as being a new publication.
57
+ [MQTT-4.3.3-2].
58
+ */
47
59
  if (ctx.store) {
48
- ctx.store.pendingIncoming.set(packet.id, packet);
60
+ if (!ctx.store.pendingIncoming.has(packet.id)) {
61
+ ctx.store.pendingIncoming.set(packet.id, packet);
62
+ ctx.persistence.publish(packet.topic, packet);
63
+ }
49
64
  await ctx.send({
50
65
  type: PacketType.pubrec,
51
66
  protocolLevel: ctx.protocolLevel,
@@ -1 +1 @@
1
- {"version":3,"file":"handlePublish.js","sourceRoot":"","sources":["../../../server/handlers/handlePublish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,GAAY,EAAE,KAAY;IACrD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAY,EACZ,MAAqB;IAErB,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,QAAQ;QACR,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,gBAAgB;YACtC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,GAAG,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,UAAU,CAAC,MAAM;gBACvB,aAAa,EAAE,GAAG,CAAC,aAAa;gBAChC,EAAE;aACH,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QACD,QAAQ;QACR,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACjD,MAAM,GAAG,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,UAAU,CAAC,MAAM;gBACvB,aAAa,EAAE,GAAG,CAAC,aAAa;gBAChC,EAAE,EAAE,MAAM,CAAC,EAAE;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"handlePublish.js","sourceRoot":"","sources":["../../../server/handlers/handlePublish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,GAAY,EAAE,KAAY;IACrD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC;QACvC,OAAO,GAAG,CAAC,QAAQ,CAAC,qBAAqB,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAY,EACZ,MAAqB;IAErB,IAAI,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5B,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;QACd,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,IAAI,MAAM,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC5B,QAAQ;QACR,IAAI,GAAG,KAAK,CAAC,EAAE,CAAC;YACd,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,gBAAgB;YACtC,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,GAAG,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,UAAU,CAAC,MAAM;gBACvB,aAAa,EAAE,GAAG,CAAC,aAAa;gBAChC,EAAE;aACH,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED;;;;;;;;;;;;UAYE;QACF,IAAI,GAAG,CAAC,KAAK,EAAE,CAAC;YACd,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBAC9C,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;gBACjD,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,GAAG,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,UAAU,CAAC,MAAM;gBACvB,aAAa,EAAE,GAAG,CAAC,aAAa;gBAChC,EAAE,EAAE,MAAM,CAAC,EAAE;aACd,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"handlePubrel.d.ts","sourceRoot":"","sources":["../../../server/handlers/handlePubrel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAcf"}
1
+ {"version":3,"file":"handlePubrel.d.ts","sourceRoot":"","sources":["../../../server/handlers/handlePubrel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAChC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC,CAUf"}
@@ -14,16 +14,12 @@ import { PacketType } from "../deps.js";
14
14
  export async function handlePubrel(ctx, packet) {
15
15
  const id = packet.id;
16
16
  if (ctx.store?.pendingIncoming.has(id)) {
17
- const storedPacket = ctx.store.pendingIncoming.get(id);
18
- if (storedPacket) {
19
- ctx.persistence.publish(storedPacket.topic, storedPacket);
20
- ctx.store.pendingIncoming.delete(id);
21
- await ctx.send({
22
- type: PacketType.pubcomp,
23
- protocolLevel: ctx.protocolLevel,
24
- id,
25
- });
26
- }
17
+ ctx.store.pendingIncoming.delete(id);
27
18
  }
19
+ await ctx.send({
20
+ type: PacketType.pubcomp,
21
+ protocolLevel: ctx.protocolLevel,
22
+ id,
23
+ });
28
24
  }
29
25
  //# sourceMappingURL=handlePubrel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"handlePubrel.js","sourceRoot":"","sources":["../../../server/handlers/handlePubrel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAY,EACZ,MAAoB;IAEpB,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,IAAI,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACvC,MAAM,YAAY,GAAG,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvD,IAAI,YAAY,EAAE,CAAC;YACjB,GAAG,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;YAC1D,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACrC,MAAM,GAAG,CAAC,IAAI,CAAC;gBACb,IAAI,EAAE,UAAU,CAAC,OAAO;gBACxB,aAAa,EAAE,GAAG,CAAC,aAAa;gBAChC,EAAE;aACH,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"handlePubrel.js","sourceRoot":"","sources":["../../../server/handlers/handlePubrel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAY,EACZ,MAAoB;IAEpB,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,IAAI,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACvC,GAAG,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,GAAG,CAAC,IAAI,CAAC;QACb,IAAI,EAAE,UAAU,CAAC,OAAO;QACxB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,EAAE;KACH,CAAC,CAAC;AACL,CAAC"}
@@ -11,16 +11,16 @@
11
11
  * }
12
12
  * ```
13
13
  */
14
- export declare class AsyncQueue<T> {
14
+ export declare class BufferedAsyncIterable<T> implements AsyncIterable<T> {
15
15
  #private;
16
- private queue;
17
- private maxQueueLength;
16
+ private buffer;
17
+ private bufferSize;
18
18
  private done;
19
- constructor(maxQueueLength?: number);
20
- next(): Promise<T>;
21
- close(reason?: string): void;
19
+ constructor(bufferSize?: number);
22
20
  [Symbol.asyncIterator](): AsyncGenerator<Awaited<T>, void, unknown>;
23
- push(item: T): void;
21
+ next(): T | Promise<T>;
22
+ close(reason?: string): void;
23
+ readonly push: (item: T) => void | Promise<void>;
24
24
  get isDone(): boolean;
25
25
  }
26
- //# sourceMappingURL=asyncQueue.d.ts.map
26
+ //# sourceMappingURL=BufferedAsyncIterable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BufferedAsyncIterable.d.ts","sourceRoot":"","sources":["../../utils/BufferedAsyncIterable.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAqB,CAAC,CAAC,CAAE,YAAW,aAAa,CAAC,CAAC,CAAC;;IAC/D,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,UAAU,CAAS;IAE3B,OAAO,CAAC,IAAI,CAAS;gBAIT,UAAU,GAAE,MAAa;IAK9B,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC;IAM1E,IAAI,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAYtB,KAAK,CAAC,MAAM,SAAW,GAAG,IAAI;IAO9B,QAAQ,CAAC,IAAI,GAAI,MAAM,CAAC,KAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAgB7C;IAEF,IAAI,MAAM,IAAI,OAAO,CAEpB;CACF"}
@@ -0,0 +1,70 @@
1
+ import { Deferred } from "./deferred.js";
2
+ import { ArrayQueue } from "./queue.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 BufferedAsyncIterable {
17
+ buffer;
18
+ bufferSize;
19
+ done = false;
20
+ #next;
21
+ constructor(bufferSize = 2048) {
22
+ this.buffer = new ArrayQueue();
23
+ this.bufferSize = bufferSize;
24
+ }
25
+ async *[Symbol.asyncIterator]() {
26
+ while (!this.done) {
27
+ yield this.next();
28
+ }
29
+ }
30
+ next() {
31
+ // await nextTick();
32
+ if (this.buffer.size() > 0) {
33
+ return this.buffer.dequeue();
34
+ }
35
+ else if (this.done) {
36
+ throw new Error("Closed");
37
+ }
38
+ else if (!this.#next) {
39
+ this.#next = new Deferred();
40
+ }
41
+ return this.#next.promise;
42
+ }
43
+ close(reason = "closed") {
44
+ this.done = true;
45
+ if (this.#next) {
46
+ this.#next.reject(new Error(reason));
47
+ }
48
+ }
49
+ push = (item) => {
50
+ if (this.#next) {
51
+ this.#next.resolve(item);
52
+ this.#next = undefined;
53
+ return;
54
+ }
55
+ this.buffer.enqueue(item);
56
+ if (this.buffer.size() > this.bufferSize) {
57
+ // If our current buffer has grown greater than the allowed size we adaptively
58
+ // wait for an amount of milliseconds proportional to the size of the buffer.
59
+ // This ensures backpressure is applied to the producer that is pushing items
60
+ // into the queue. Note that this might be an exceedingly simple heuristic,
61
+ // a PID (Proportional-Integral-Derivative) controller could be used to improve
62
+ // the responsiveness of the system.
63
+ return new Promise((resolve) => setTimeout(resolve, this.buffer.size()));
64
+ }
65
+ };
66
+ get isDone() {
67
+ return this.done;
68
+ }
69
+ }
70
+ //# sourceMappingURL=BufferedAsyncIterable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BufferedAsyncIterable.js","sourceRoot":"","sources":["../../utils/BufferedAsyncIterable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,qBAAqB;IACxB,MAAM,CAAgB;IACtB,UAAU,CAAS;IAEnB,IAAI,GAAG,KAAK,CAAC;IAErB,KAAK,CAAe;IAEpB,YAAY,aAAqB,IAAI;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC/B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAClB,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACpB,CAAC;IACH,CAAC;IAED,IAAI;QACF,oBAAoB;QACpB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAG,CAAC;QAChC,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC5B,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;IAEQ,IAAI,GAAG,CAAC,IAAO,EAAwB,EAAE;QAChD,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,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC1B,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YACzC,8EAA8E;YAC9E,6EAA6E;YAC7E,6EAA6E;YAC7E,2EAA2E;YAC3E,+EAA+E;YAC/E,oCAAoC;YACpC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -5,6 +5,5 @@
5
5
  export { assert } from "./assert.ts";
6
6
  export { Deferred } from "./deferred.ts";
7
7
  export { Logger, logger, LogLevel } from "./logger.ts";
8
- export { AsyncQueue } from "./asyncQueue.ts";
9
- export { nextTick } from "./nextTick.ts";
8
+ export { BufferedAsyncIterable } from "./BufferedAsyncIterable.ts";
10
9
  //# sourceMappingURL=mod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"mod.d.ts","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
package/dist/utils/mod.js CHANGED
@@ -5,6 +5,5 @@
5
5
  export { assert } from "./assert.js";
6
6
  export { Deferred } from "./deferred.js";
7
7
  export { Logger, logger, LogLevel } from "./logger.js";
8
- export { AsyncQueue } from "./asyncQueue.js";
9
- export { nextTick } from "./nextTick.js";
8
+ export { BufferedAsyncIterable } from "./BufferedAsyncIterable.js";
10
9
  //# sourceMappingURL=mod.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"mod.js","sourceRoot":"","sources":["../../utils/mod.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
@@ -0,0 +1,43 @@
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
+ export declare class ArrayQueue<T> {
19
+ private items;
20
+ private headIndex;
21
+ /**
22
+ * size is the difference between the actual array length and the index offset
23
+ * @returns the number of items in the queue
24
+ */
25
+ size(): number;
26
+ /**
27
+ * isEmpty checks if the queue has no items
28
+ * @returns true if the queue is empty
29
+ */
30
+ isEmpty(): boolean;
31
+ /**
32
+ * enqueue adds an item to the end of the queue
33
+ * O(1) - Push to the end is highly optimized in V8.
34
+ */
35
+ enqueue(data: T): void;
36
+ /**
37
+ * dequeue removes and returns the item at the front of the queue
38
+ * O(1) - Avoids array shifting by incrementing the index.
39
+ * @returns the item at the front of the queue or undefined if the queue is empty
40
+ */
41
+ dequeue(): T | undefined;
42
+ }
43
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../utils/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,qBAAa,UAAU,CAAC,CAAC;IACvB,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,SAAS,CAAa;IAE9B;;;OAGG;IACI,IAAI,IAAI,MAAM;IAGrB;;;OAGG;IACI,OAAO,IAAI,OAAO;IAGzB;;;OAGG;IACI,OAAO,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAG7B;;;;OAIG;IACI,OAAO,IAAI,CAAC,GAAG,SAAS;CAiBhC"}
@@ -0,0 +1,63 @@
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
+ export class ArrayQueue {
19
+ items = [];
20
+ headIndex = 0; // Tracks the front of the queue
21
+ /**
22
+ * size is the difference between the actual array length and the index offset
23
+ * @returns the number of items in the queue
24
+ */
25
+ size() {
26
+ return this.items.length - this.headIndex;
27
+ }
28
+ /**
29
+ * isEmpty checks if the queue has no items
30
+ * @returns true if the queue is empty
31
+ */
32
+ isEmpty() {
33
+ return this.size() === 0;
34
+ }
35
+ /**
36
+ * enqueue adds an item to the end of the queue
37
+ * O(1) - Push to the end is highly optimized in V8.
38
+ */
39
+ enqueue(data) {
40
+ this.items.push(data);
41
+ }
42
+ /**
43
+ * dequeue removes and returns the item at the front of the queue
44
+ * O(1) - Avoids array shifting by incrementing the index.
45
+ * @returns the item at the front of the queue or undefined if the queue is empty
46
+ */
47
+ dequeue() {
48
+ if (this.isEmpty()) {
49
+ return undefined;
50
+ }
51
+ const item = this.items[this.headIndex];
52
+ this.headIndex++; // Move the "front" marker forward
53
+ // Optimization: Periodically "clean up" the dead space
54
+ // when the empty space (headIndex) exceeds a threshold.
55
+ // This amortizes the cost, keeping average time closer to O(1).
56
+ if (this.headIndex > 2000 && this.headIndex > this.items.length / 4) {
57
+ this.items = this.items.slice(this.headIndex);
58
+ this.headIndex = 0;
59
+ }
60
+ return item;
61
+ }
62
+ }
63
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../utils/queue.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,OAAO,UAAU;IACb,KAAK,GAAQ,EAAE,CAAC;IAChB,SAAS,GAAW,CAAC,CAAC,CAAC,gCAAgC;IAE/D;;;OAGG;IACI,IAAI;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC;IAC5C,CAAC;IACD;;;OAGG;IACI,OAAO;QACZ,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC3B,CAAC;IACD;;;OAGG;IACI,OAAO,CAAC,IAAO;QACpB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IACD;;;;OAIG;IACI,OAAO;QACZ,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;YACnB,OAAO,SAAS,CAAC;QACnB,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,kCAAkC;QAEpD,uDAAuD;QACvD,wDAAwD;QACxD,gEAAgE;QAChE,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC9C,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -72,7 +72,6 @@ test("Test pubSub using client and server", async function () {
72
72
 
73
73
  await sleep(100);
74
74
  logger.verbose(`Disconnect client`);
75
- //client.closeMessages();
76
75
  await client.disconnect();
77
76
 
78
77
  logger.verbose(`Check completeness`);
@@ -56,7 +56,7 @@ test("MqttConn should act as asyncIterator", async () => {
56
56
  );
57
57
  const mqttConn = new MqttConn({ conn, protocolLevel: 4 });
58
58
 
59
- const packets = [];
59
+ const packets: AnyPacket[] = [];
60
60
  for await (const packet of mqttConn) {
61
61
  packets.push(packet);
62
62
  }
@@ -71,7 +71,7 @@ test("MqttConn should close on malformed length", async () => {
71
71
  const conn = makeDummySockConn([new Uint8Array([1, 175])], new Uint8Array());
72
72
  const mqttConn = new MqttConn({ conn });
73
73
 
74
- const packets = [];
74
+ const packets: AnyPacket[] = [];
75
75
  for await (const packet of mqttConn) {
76
76
  packets.push(packet);
77
77
  }
@@ -89,7 +89,7 @@ test("MqttConn should close on failed packets", async () => {
89
89
  const conn = makeDummySockConn([connect, brokenPublish], new Uint8Array());
90
90
  const mqttConn = new MqttConn({ conn });
91
91
 
92
- const packets = [];
92
+ const packets: AnyPacket[] = [];
93
93
  for await (const packet of mqttConn) {
94
94
  packets.push(packet);
95
95
  }
@@ -105,7 +105,8 @@ test("MqttConn should close on packets too large", async () => {
105
105
 
106
106
  const conn = makeDummySockConn([connect], new Uint8Array());
107
107
  const mqttConn = new MqttConn({ conn, maxIncomingPacketSize: 20 });
108
- const packets = [];
108
+
109
+ const packets: AnyPacket[] = [];
109
110
  for await (const packet of mqttConn) {
110
111
  packets.push(packet);
111
112
  }
@@ -41,8 +41,6 @@ export interface IMqttConn extends AsyncIterable<AnyPacket> {
41
41
  readonly isClosed: boolean;
42
42
  /** Reason for connection closure if any */
43
43
  readonly reason: string | undefined;
44
- /** Async iterator for receiving packets */
45
- [Symbol.asyncIterator](): AsyncIterableIterator<AnyPacket>;
46
44
  /** Send an MQTT packet */
47
45
  send(data: AnyPacket): Promise<void>;
48
46
  /** Close the connection */
@@ -166,27 +164,33 @@ export class MqttConn implements IMqttConn {
166
164
  }
167
165
 
168
166
  /**
169
- * Async iterator for receiving packets
170
- * @yields MQTT packets
167
+ * Returns incoming MQTT packages until the connection is closed. Note that
168
+ * the connection will close automatically upon receiving an invalid packet.
169
+ *
170
+ * @returns a Promise that resolves to AnyPacket if the connection is open
171
+ * and working nominally, undefined otherwise.
171
172
  */
172
- async *[Symbol.asyncIterator](): AsyncIterableIterator<AnyPacket> {
173
- while (!this._isClosed) {
174
- try {
175
- yield await readPacket(
176
- this.conn,
177
- this.codecOpts,
178
- );
179
- } catch (err) {
173
+ #receive(): Promise<AnyPacket | undefined> {
174
+ if (!this._isClosed) {
175
+ return readPacket(this.conn, this.codecOpts).catch((err) => {
180
176
  if (err instanceof Error) {
181
177
  if (err.name === "PartialReadError") {
182
178
  err.message = MqttConnError.UnexpectedEof;
183
179
  }
184
180
  this._reason = err.message;
185
181
  }
186
- // packet too large, malformed packet or connection closed
182
+ // packet too large, malformed packet or connection closed.
187
183
  this.close();
188
- break;
189
- }
184
+ return undefined;
185
+ });
186
+ }
187
+ return Promise.resolve(undefined);
188
+ }
189
+
190
+ async *[Symbol.asyncIterator](): AsyncIterator<AnyPacket> {
191
+ let packet: AnyPacket | undefined;
192
+ while ((packet = await this.#receive()) !== undefined) {
193
+ yield packet;
190
194
  }
191
195
  }
192
196
 
@@ -72,7 +72,6 @@ test("Test pubSub using client and server", async function () {
72
72
 
73
73
  await sleep(100);
74
74
  logger.verbose(`Disconnect client`);
75
- //client.closeMessages();
76
75
  await client.disconnect();
77
76
 
78
77
  logger.verbose(`Check completeness`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seriousme/opifex",
3
- "version": "1.11.0",
3
+ "version": "1.11.2",
4
4
  "description": "MQTT client & server for Deno & NodeJS",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -52,9 +52,25 @@ export async function handlePublish(
52
52
  });
53
53
  return;
54
54
  }
55
- // qos 2
55
+
56
+ /*
57
+ In the QoS 2 delivery protocol, the Receiver
58
+
59
+ - MUST respond with a PUBREC containing the Packet Identifier from the incoming PUBLISH Packet,
60
+ having accepted ownership of the Application Message.
61
+ - Until it has received the corresponding PUBREL packet, the Receiver MUST acknowledge any subsequent
62
+ PUBLISH packet with the same Packet Identifier by sending a PUBREC. It MUST NOT cause duplicate
63
+ messages to be delivered to any onward recipients in this case.
64
+ - MUST respond to a PUBREL packet by sending a PUBCOMP packet containing the same Packet Identifier as the PUBREL.
65
+ - After it has sent a PUBCOMP, the receiver MUST treat any subsequent PUBLISH packet that contains that Packet
66
+ Identifier as being a new publication.
67
+ [MQTT-4.3.3-2].
68
+ */
56
69
  if (ctx.store) {
57
- ctx.store.pendingIncoming.set(packet.id, packet);
70
+ if (!ctx.store.pendingIncoming.has(packet.id)) {
71
+ ctx.store.pendingIncoming.set(packet.id, packet);
72
+ ctx.persistence.publish(packet.topic, packet);
73
+ }
58
74
  await ctx.send({
59
75
  type: PacketType.pubrec,
60
76
  protocolLevel: ctx.protocolLevel,
@@ -20,15 +20,11 @@ export async function handlePubrel(
20
20
  ): Promise<void> {
21
21
  const id = packet.id;
22
22
  if (ctx.store?.pendingIncoming.has(id)) {
23
- const storedPacket = ctx.store.pendingIncoming.get(id);
24
- if (storedPacket) {
25
- ctx.persistence.publish(storedPacket.topic, storedPacket);
26
- ctx.store.pendingIncoming.delete(id);
27
- await ctx.send({
28
- type: PacketType.pubcomp,
29
- protocolLevel: ctx.protocolLevel,
30
- id,
31
- });
32
- }
23
+ ctx.store.pendingIncoming.delete(id);
33
24
  }
25
+ await ctx.send({
26
+ type: PacketType.pubcomp,
27
+ protocolLevel: ctx.protocolLevel,
28
+ id,
29
+ });
34
30
  }