@procwire/transport 0.1.3 → 0.3.0

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 (142) hide show
  1. package/README.md +130 -4
  2. package/dist/channel/builder.d.ts +17 -0
  3. package/dist/channel/builder.d.ts.map +1 -1
  4. package/dist/channel/builder.js +34 -0
  5. package/dist/channel/builder.js.map +1 -1
  6. package/dist/channel/index.d.ts +1 -1
  7. package/dist/channel/index.d.ts.map +1 -1
  8. package/dist/channel/index.js +1 -1
  9. package/dist/channel/index.js.map +1 -1
  10. package/dist/channel/quickstart.d.ts.map +1 -1
  11. package/dist/channel/quickstart.js +16 -10
  12. package/dist/channel/quickstart.js.map +1 -1
  13. package/dist/channel/request-channel.d.ts +6 -1
  14. package/dist/channel/request-channel.d.ts.map +1 -1
  15. package/dist/channel/request-channel.js +138 -34
  16. package/dist/channel/request-channel.js.map +1 -1
  17. package/dist/channel/types.d.ts +129 -7
  18. package/dist/channel/types.d.ts.map +1 -1
  19. package/dist/framing/length-prefixed.d.ts +5 -1
  20. package/dist/framing/length-prefixed.d.ts.map +1 -1
  21. package/dist/framing/length-prefixed.js +94 -15
  22. package/dist/framing/length-prefixed.js.map +1 -1
  23. package/dist/framing/line-delimited.d.ts +4 -1
  24. package/dist/framing/line-delimited.d.ts.map +1 -1
  25. package/dist/framing/line-delimited.js +89 -23
  26. package/dist/framing/line-delimited.js.map +1 -1
  27. package/dist/heartbeat/constants.d.ts +12 -0
  28. package/dist/heartbeat/constants.d.ts.map +1 -0
  29. package/dist/heartbeat/constants.js +17 -0
  30. package/dist/heartbeat/constants.js.map +1 -0
  31. package/dist/heartbeat/index.d.ts +10 -0
  32. package/dist/heartbeat/index.d.ts.map +1 -0
  33. package/dist/heartbeat/index.js +10 -0
  34. package/dist/heartbeat/index.js.map +1 -0
  35. package/dist/heartbeat/manager.d.ts +107 -0
  36. package/dist/heartbeat/manager.d.ts.map +1 -0
  37. package/dist/heartbeat/manager.js +252 -0
  38. package/dist/heartbeat/manager.js.map +1 -0
  39. package/dist/heartbeat/types.d.ts +99 -0
  40. package/dist/heartbeat/types.d.ts.map +1 -0
  41. package/dist/heartbeat/types.js +8 -0
  42. package/dist/heartbeat/types.js.map +1 -0
  43. package/dist/index.d.ts +4 -0
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +5 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/process/handle.d.ts.map +1 -1
  48. package/dist/process/handle.js.map +1 -1
  49. package/dist/process/manager.d.ts +16 -0
  50. package/dist/process/manager.d.ts.map +1 -1
  51. package/dist/process/manager.js +133 -82
  52. package/dist/process/manager.js.map +1 -1
  53. package/dist/process/types.d.ts +110 -1
  54. package/dist/process/types.d.ts.map +1 -1
  55. package/dist/protocol/index.d.ts +2 -0
  56. package/dist/protocol/index.d.ts.map +1 -1
  57. package/dist/protocol/index.js +3 -0
  58. package/dist/protocol/index.js.map +1 -1
  59. package/dist/protocol/jsonrpc.d.ts.map +1 -1
  60. package/dist/protocol/jsonrpc.js.map +1 -1
  61. package/dist/protocol/reserved-methods.d.ts +90 -0
  62. package/dist/protocol/reserved-methods.d.ts.map +1 -0
  63. package/dist/protocol/reserved-methods.js +99 -0
  64. package/dist/protocol/reserved-methods.js.map +1 -0
  65. package/dist/protocol/reserved-types.d.ts +231 -0
  66. package/dist/protocol/reserved-types.d.ts.map +1 -0
  67. package/dist/protocol/reserved-types.js +10 -0
  68. package/dist/protocol/reserved-types.js.map +1 -0
  69. package/dist/protocol/simple.d.ts.map +1 -1
  70. package/dist/protocol/simple.js.map +1 -1
  71. package/dist/reconnect/constants.d.ts +12 -0
  72. package/dist/reconnect/constants.d.ts.map +1 -0
  73. package/dist/reconnect/constants.js +21 -0
  74. package/dist/reconnect/constants.js.map +1 -0
  75. package/dist/reconnect/index.d.ts +10 -0
  76. package/dist/reconnect/index.d.ts.map +1 -0
  77. package/dist/reconnect/index.js +10 -0
  78. package/dist/reconnect/index.js.map +1 -0
  79. package/dist/reconnect/manager.d.ts +110 -0
  80. package/dist/reconnect/manager.d.ts.map +1 -0
  81. package/dist/reconnect/manager.js +264 -0
  82. package/dist/reconnect/manager.js.map +1 -0
  83. package/dist/reconnect/types.d.ts +137 -0
  84. package/dist/reconnect/types.d.ts.map +1 -0
  85. package/dist/reconnect/types.js +8 -0
  86. package/dist/reconnect/types.js.map +1 -0
  87. package/dist/resilience/handle.d.ts +112 -0
  88. package/dist/resilience/handle.d.ts.map +1 -0
  89. package/dist/resilience/handle.js +371 -0
  90. package/dist/resilience/handle.js.map +1 -0
  91. package/dist/resilience/index.d.ts +9 -0
  92. package/dist/resilience/index.d.ts.map +1 -0
  93. package/dist/resilience/index.js +9 -0
  94. package/dist/resilience/index.js.map +1 -0
  95. package/dist/resilience/types.d.ts +191 -0
  96. package/dist/resilience/types.d.ts.map +1 -0
  97. package/dist/resilience/types.js +8 -0
  98. package/dist/resilience/types.js.map +1 -0
  99. package/dist/serialization/json.d.ts.map +1 -1
  100. package/dist/serialization/json.js.map +1 -1
  101. package/dist/shutdown/constants.d.ts +12 -0
  102. package/dist/shutdown/constants.d.ts.map +1 -0
  103. package/dist/shutdown/constants.js +15 -0
  104. package/dist/shutdown/constants.js.map +1 -0
  105. package/dist/shutdown/index.d.ts +10 -0
  106. package/dist/shutdown/index.d.ts.map +1 -0
  107. package/dist/shutdown/index.js +10 -0
  108. package/dist/shutdown/index.js.map +1 -0
  109. package/dist/shutdown/manager.d.ts +102 -0
  110. package/dist/shutdown/manager.d.ts.map +1 -0
  111. package/dist/shutdown/manager.js +252 -0
  112. package/dist/shutdown/manager.js.map +1 -0
  113. package/dist/shutdown/types.d.ts +133 -0
  114. package/dist/shutdown/types.d.ts.map +1 -0
  115. package/dist/shutdown/types.js +8 -0
  116. package/dist/shutdown/types.js.map +1 -0
  117. package/dist/transport/socket-server.d.ts.map +1 -1
  118. package/dist/transport/socket-server.js.map +1 -1
  119. package/dist/transport/socket-transport.d.ts +11 -13
  120. package/dist/transport/socket-transport.d.ts.map +1 -1
  121. package/dist/transport/socket-transport.js +57 -26
  122. package/dist/transport/socket-transport.js.map +1 -1
  123. package/dist/transport/stdio-transport.d.ts +12 -19
  124. package/dist/transport/stdio-transport.d.ts.map +1 -1
  125. package/dist/transport/stdio-transport.js +54 -33
  126. package/dist/transport/stdio-transport.js.map +1 -1
  127. package/dist/utils/index.d.ts +1 -0
  128. package/dist/utils/index.d.ts.map +1 -1
  129. package/dist/utils/index.js +1 -0
  130. package/dist/utils/index.js.map +1 -1
  131. package/dist/utils/metrics.d.ts +6 -0
  132. package/dist/utils/metrics.d.ts.map +1 -0
  133. package/dist/utils/metrics.js +2 -0
  134. package/dist/utils/metrics.js.map +1 -0
  135. package/dist/utils/pipe-path.d.ts +8 -2
  136. package/dist/utils/pipe-path.d.ts.map +1 -1
  137. package/dist/utils/pipe-path.js +27 -4
  138. package/dist/utils/pipe-path.js.map +1 -1
  139. package/dist/utils/platform.d.ts.map +1 -1
  140. package/dist/utils/platform.js +1 -1
  141. package/dist/utils/platform.js.map +1 -1
  142. package/package.json +1 -1
@@ -17,11 +17,17 @@ import { FramingError } from "../utils/errors.js";
17
17
  export class LengthPrefixedFraming {
18
18
  static HEADER_SIZE = 4;
19
19
  maxMessageSize;
20
- buffer;
20
+ buffers;
21
+ totalLength;
21
22
  expectedLength;
22
23
  constructor(options = {}) {
24
+ // Validate options
25
+ if (options.maxMessageSize !== undefined && options.maxMessageSize <= 0) {
26
+ throw new Error("LengthPrefixedFraming: maxMessageSize must be positive");
27
+ }
23
28
  this.maxMessageSize = options.maxMessageSize ?? 32 * 1024 * 1024; // 32MB
24
- this.buffer = Buffer.allocUnsafe(0);
29
+ this.buffers = [];
30
+ this.totalLength = 0;
25
31
  this.expectedLength = null;
26
32
  }
27
33
  /**
@@ -37,19 +43,26 @@ export class LengthPrefixedFraming {
37
43
  * Buffers partial headers and payloads.
38
44
  */
39
45
  decode(chunk) {
40
- // Append chunk to buffer
41
- this.buffer = Buffer.concat([this.buffer, chunk]);
46
+ // Append chunk to buffer list
47
+ if (chunk.length > 0) {
48
+ this.buffers.push(chunk);
49
+ this.totalLength += chunk.length;
50
+ }
42
51
  const frames = [];
43
52
  // Process all complete frames in buffer
44
53
  while (true) {
45
54
  // Do we need to read the header?
46
55
  if (this.expectedLength === null) {
47
56
  // Need at least HEADER_SIZE bytes
48
- if (this.buffer.length < LengthPrefixedFraming.HEADER_SIZE) {
57
+ if (this.totalLength < LengthPrefixedFraming.HEADER_SIZE) {
49
58
  break; // Wait for more data
50
59
  }
51
60
  // Read length from header
52
- const length = this.buffer.readUInt32BE(0);
61
+ const header = this.peekBytes(LengthPrefixedFraming.HEADER_SIZE);
62
+ if (!header) {
63
+ break;
64
+ }
65
+ const length = header.readUInt32BE(0);
53
66
  // Validate length
54
67
  if (length > this.maxMessageSize) {
55
68
  const error = new FramingError(`Message length ${length} exceeds maximum ${this.maxMessageSize}`);
@@ -57,23 +70,22 @@ export class LengthPrefixedFraming {
57
70
  throw error;
58
71
  }
59
72
  this.expectedLength = length;
60
- this.buffer = this.buffer.subarray(LengthPrefixedFraming.HEADER_SIZE);
73
+ this.consumeBytes(LengthPrefixedFraming.HEADER_SIZE);
61
74
  }
62
75
  // Do we have the complete payload?
63
- if (this.buffer.length < this.expectedLength) {
76
+ if (this.totalLength < this.expectedLength) {
64
77
  break; // Wait for more data
65
78
  }
66
79
  // Extract frame
67
- const frame = this.buffer.subarray(0, this.expectedLength);
80
+ const frame = this.takeBytes(this.expectedLength);
68
81
  frames.push(frame);
69
82
  // Move past this frame
70
- this.buffer = this.buffer.subarray(this.expectedLength);
71
83
  this.expectedLength = null;
72
84
  }
73
85
  // Validate buffer doesn't grow unbounded
74
86
  const maxBufferSize = LengthPrefixedFraming.HEADER_SIZE + this.maxMessageSize;
75
- if (this.buffer.length > maxBufferSize) {
76
- const error = new FramingError(`Buffer size ${this.buffer.length} exceeds maximum ${maxBufferSize}`);
87
+ if (this.totalLength > maxBufferSize) {
88
+ const error = new FramingError(`Buffer size ${this.totalLength} exceeds maximum ${maxBufferSize}`);
77
89
  this.reset();
78
90
  throw error;
79
91
  }
@@ -83,20 +95,87 @@ export class LengthPrefixedFraming {
83
95
  * Resets internal buffer state.
84
96
  */
85
97
  reset() {
86
- this.buffer = Buffer.allocUnsafe(0);
98
+ this.buffers = [];
99
+ this.totalLength = 0;
87
100
  this.expectedLength = null;
88
101
  }
89
102
  /**
90
103
  * Returns true if there is buffered partial data.
91
104
  */
92
105
  hasBufferedData() {
93
- return this.buffer.length > 0 || this.expectedLength !== null;
106
+ return this.totalLength > 0 || this.expectedLength !== null;
94
107
  }
95
108
  /**
96
109
  * Returns current buffer size in bytes.
97
110
  */
98
111
  getBufferSize() {
99
- return this.buffer.length;
112
+ return this.totalLength;
113
+ }
114
+ peekBytes(length) {
115
+ if (length > this.totalLength || this.buffers.length === 0) {
116
+ return null;
117
+ }
118
+ const first = this.buffers[0];
119
+ if (first.length >= length) {
120
+ return first.subarray(0, length);
121
+ }
122
+ const parts = [];
123
+ let remaining = length;
124
+ for (const buffer of this.buffers) {
125
+ const slice = buffer.subarray(0, Math.min(buffer.length, remaining));
126
+ parts.push(slice);
127
+ remaining -= slice.length;
128
+ if (remaining === 0) {
129
+ break;
130
+ }
131
+ }
132
+ return Buffer.concat(parts, length);
133
+ }
134
+ takeBytes(length) {
135
+ if (length === 0) {
136
+ return Buffer.allocUnsafe(0);
137
+ }
138
+ if (length > this.totalLength) {
139
+ return Buffer.allocUnsafe(0);
140
+ }
141
+ const first = this.buffers[0];
142
+ if (first.length >= length) {
143
+ const slice = first.subarray(0, length);
144
+ this.consumeBytes(length);
145
+ return slice;
146
+ }
147
+ const parts = [];
148
+ let remaining = length;
149
+ while (remaining > 0 && this.buffers.length > 0) {
150
+ const buffer = this.buffers[0];
151
+ if (remaining >= buffer.length) {
152
+ parts.push(buffer);
153
+ this.buffers.shift();
154
+ remaining -= buffer.length;
155
+ }
156
+ else {
157
+ parts.push(buffer.subarray(0, remaining));
158
+ this.buffers[0] = buffer.subarray(remaining);
159
+ remaining = 0;
160
+ }
161
+ }
162
+ this.totalLength -= length;
163
+ return parts.length === 1 ? parts[0] : Buffer.concat(parts, length);
164
+ }
165
+ consumeBytes(length) {
166
+ let remaining = length;
167
+ while (remaining > 0 && this.buffers.length > 0) {
168
+ const buffer = this.buffers[0];
169
+ if (remaining >= buffer.length) {
170
+ this.buffers.shift();
171
+ remaining -= buffer.length;
172
+ }
173
+ else {
174
+ this.buffers[0] = buffer.subarray(remaining);
175
+ remaining = 0;
176
+ }
177
+ }
178
+ this.totalLength -= length;
100
179
  }
101
180
  }
102
181
  //# sourceMappingURL=length-prefixed.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"length-prefixed.js","sourceRoot":"","sources":["../../src/framing/length-prefixed.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"length-prefixed.js","sourceRoot":"","sources":["../../src/framing/length-prefixed.ts"],"names":[],"mappings":"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"}
@@ -33,7 +33,8 @@ export declare class LineDelimitedFraming implements FramingCodec {
33
33
  private readonly delimiter;
34
34
  private readonly maxBufferSize;
35
35
  private readonly stripDelimiter;
36
- private buffer;
36
+ private buffers;
37
+ private totalLength;
37
38
  constructor(options?: LineDelimitedFramingOptions);
38
39
  /**
39
40
  * Encodes a payload with delimiter.
@@ -57,5 +58,7 @@ export declare class LineDelimitedFraming implements FramingCodec {
57
58
  * Returns current buffer size in bytes.
58
59
  */
59
60
  getBufferSize(): number;
61
+ private buildFrame;
62
+ private compactBuffers;
60
63
  }
61
64
  //# sourceMappingURL=line-delimited.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-delimited.d.ts","sourceRoot":"","sources":["../../src/framing/line-delimited.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,MAAM,CAAS;gBAEX,OAAO,GAAE,2BAAgC;IAOrD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAa/B;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IA0C/B;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,aAAa,IAAI,MAAM;CAGxB"}
1
+ {"version":3,"file":"line-delimited.d.ts","sourceRoot":"","sources":["../../src/framing/line-delimited.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;OAEG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,oBAAqB,YAAW,YAAY;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAU;IACzC,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,WAAW,CAAS;gBAEhB,OAAO,GAAE,2BAAgC;IAgBrD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAa/B;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAwD/B;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,aAAa,IAAI,MAAM;IAIvB,OAAO,CAAC,UAAU;IA8BlB,OAAO,CAAC,cAAc;CA4BvB"}
@@ -15,12 +15,21 @@ export class LineDelimitedFraming {
15
15
  delimiter;
16
16
  maxBufferSize;
17
17
  stripDelimiter;
18
- buffer;
18
+ buffers;
19
+ totalLength;
19
20
  constructor(options = {}) {
21
+ // Validate options
22
+ if (options.delimiter !== undefined && (options.delimiter < 0 || options.delimiter > 255)) {
23
+ throw new Error("LineDelimitedFraming: delimiter must be a byte value (0-255)");
24
+ }
25
+ if (options.maxBufferSize !== undefined && options.maxBufferSize <= 0) {
26
+ throw new Error("LineDelimitedFraming: maxBufferSize must be positive");
27
+ }
20
28
  this.delimiter = options.delimiter ?? 0x0a; // '\n'
21
29
  this.maxBufferSize = options.maxBufferSize ?? 8 * 1024 * 1024; // 8MB
22
30
  this.stripDelimiter = options.stripDelimiter ?? true;
23
- this.buffer = Buffer.allocUnsafe(0);
31
+ this.buffers = [];
32
+ this.totalLength = 0;
24
33
  }
25
34
  /**
26
35
  * Encodes a payload with delimiter.
@@ -42,53 +51,110 @@ export class LineDelimitedFraming {
42
51
  * Buffers partial data until delimiter is found.
43
52
  */
44
53
  decode(chunk) {
45
- // Append chunk to buffer
46
- this.buffer = Buffer.concat([this.buffer, chunk]);
54
+ // Append chunk to buffer list
55
+ if (chunk.length > 0) {
56
+ this.buffers.push(chunk);
57
+ this.totalLength += chunk.length;
58
+ }
47
59
  // Check buffer size limit
48
- if (this.buffer.length > this.maxBufferSize) {
49
- const error = new FramingError(`Buffer size ${this.buffer.length} exceeds maximum ${this.maxBufferSize}`);
60
+ if (this.totalLength > this.maxBufferSize) {
61
+ const error = new FramingError(`Buffer size ${this.totalLength} exceeds maximum ${this.maxBufferSize}`);
50
62
  this.reset();
51
63
  throw error;
52
64
  }
53
65
  const frames = [];
54
- let searchStart = 0;
66
+ let frameStartBufferIndex = 0;
67
+ let frameStartOffset = 0;
68
+ let bufferIndex = 0;
69
+ let searchOffset = 0;
55
70
  // Find all complete frames (terminated by delimiter)
56
- while (searchStart < this.buffer.length) {
57
- const delimiterIndex = this.buffer.indexOf(this.delimiter, searchStart);
71
+ while (bufferIndex < this.buffers.length) {
72
+ const buffer = this.buffers[bufferIndex];
73
+ const delimiterIndex = buffer.indexOf(this.delimiter, searchOffset);
58
74
  if (delimiterIndex === -1) {
59
- // No more delimiters found
60
- break;
75
+ bufferIndex++;
76
+ searchOffset = 0;
77
+ continue;
61
78
  }
62
- // Extract frame
63
- const frameEnd = this.stripDelimiter ? delimiterIndex : delimiterIndex + 1;
64
- const frame = this.buffer.subarray(searchStart, frameEnd);
65
- frames.push(frame);
79
+ const frameEndOffset = this.stripDelimiter ? delimiterIndex : delimiterIndex + 1;
80
+ frames.push(this.buildFrame(frameStartBufferIndex, frameStartOffset, bufferIndex, frameEndOffset));
66
81
  // Move past delimiter
67
- searchStart = delimiterIndex + 1;
68
- }
69
- // Keep remaining data in buffer
70
- if (searchStart > 0) {
71
- this.buffer = this.buffer.subarray(searchStart);
82
+ if (delimiterIndex + 1 < buffer.length) {
83
+ frameStartBufferIndex = bufferIndex;
84
+ frameStartOffset = delimiterIndex + 1;
85
+ searchOffset = frameStartOffset;
86
+ }
87
+ else {
88
+ frameStartBufferIndex = bufferIndex + 1;
89
+ frameStartOffset = 0;
90
+ bufferIndex = frameStartBufferIndex;
91
+ searchOffset = 0;
92
+ }
72
93
  }
94
+ this.compactBuffers(frameStartBufferIndex, frameStartOffset);
73
95
  return frames;
74
96
  }
75
97
  /**
76
98
  * Resets internal buffer state.
77
99
  */
78
100
  reset() {
79
- this.buffer = Buffer.allocUnsafe(0);
101
+ this.buffers = [];
102
+ this.totalLength = 0;
80
103
  }
81
104
  /**
82
105
  * Returns true if there is buffered partial data.
83
106
  */
84
107
  hasBufferedData() {
85
- return this.buffer.length > 0;
108
+ return this.totalLength > 0;
86
109
  }
87
110
  /**
88
111
  * Returns current buffer size in bytes.
89
112
  */
90
113
  getBufferSize() {
91
- return this.buffer.length;
114
+ return this.totalLength;
115
+ }
116
+ buildFrame(startIndex, startOffset, endIndex, endOffset) {
117
+ if (startIndex === endIndex) {
118
+ return this.buffers[startIndex].subarray(startOffset, endOffset);
119
+ }
120
+ const parts = [];
121
+ let totalLength = 0;
122
+ const first = this.buffers[startIndex].subarray(startOffset);
123
+ parts.push(first);
124
+ totalLength += first.length;
125
+ for (let i = startIndex + 1; i < endIndex; i++) {
126
+ const buffer = this.buffers[i];
127
+ parts.push(buffer);
128
+ totalLength += buffer.length;
129
+ }
130
+ const last = this.buffers[endIndex].subarray(0, endOffset);
131
+ parts.push(last);
132
+ totalLength += last.length;
133
+ return Buffer.concat(parts, totalLength);
134
+ }
135
+ compactBuffers(startIndex, startOffset) {
136
+ if (startIndex === 0 && startOffset === 0) {
137
+ return;
138
+ }
139
+ if (startIndex >= this.buffers.length) {
140
+ this.buffers = [];
141
+ this.totalLength = 0;
142
+ return;
143
+ }
144
+ const nextBuffers = [];
145
+ let nextLength = 0;
146
+ for (let i = startIndex; i < this.buffers.length; i++) {
147
+ let buffer = this.buffers[i];
148
+ if (i === startIndex && startOffset > 0) {
149
+ buffer = buffer.subarray(startOffset);
150
+ }
151
+ if (buffer.length > 0) {
152
+ nextBuffers.push(buffer);
153
+ nextLength += buffer.length;
154
+ }
155
+ }
156
+ this.buffers = nextBuffers;
157
+ this.totalLength = nextLength;
92
158
  }
93
159
  }
94
160
  //# sourceMappingURL=line-delimited.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-delimited.js","sourceRoot":"","sources":["../../src/framing/line-delimited.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"line-delimited.js","sourceRoot":"","sources":["../../src/framing/line-delimited.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Heartbeat manager constants.
3
+ *
4
+ * @packageDocumentation
5
+ * @module Heartbeat
6
+ */
7
+ import type { HeartbeatOptions } from "./types.js";
8
+ /**
9
+ * Default heartbeat configuration options.
10
+ */
11
+ export declare const DEFAULT_HEARTBEAT_OPTIONS: Readonly<Required<HeartbeatOptions>>;
12
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/heartbeat/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,yBAAyB,EAAE,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAM1E,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Heartbeat manager constants.
3
+ *
4
+ * @packageDocumentation
5
+ * @module Heartbeat
6
+ */
7
+ /**
8
+ * Default heartbeat configuration options.
9
+ */
10
+ export const DEFAULT_HEARTBEAT_OPTIONS = {
11
+ enabled: true,
12
+ interval: 30_000,
13
+ timeout: 5_000,
14
+ maxMissed: 3,
15
+ implicitHeartbeat: true,
16
+ };
17
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/heartbeat/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;GAEG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAyC;IAC7E,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,MAAM;IAChB,OAAO,EAAE,KAAK;IACd,SAAS,EAAE,CAAC;IACZ,iBAAiB,EAAE,IAAI;CACxB,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Heartbeat module for detecting unresponsive workers.
3
+ *
4
+ * @packageDocumentation
5
+ * @module Heartbeat
6
+ */
7
+ export * from "./types.js";
8
+ export * from "./constants.js";
9
+ export * from "./manager.js";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/heartbeat/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Heartbeat module for detecting unresponsive workers.
3
+ *
4
+ * @packageDocumentation
5
+ * @module Heartbeat
6
+ */
7
+ export * from "./types.js";
8
+ export * from "./constants.js";
9
+ export * from "./manager.js";
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/heartbeat/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * HeartbeatManager implementation.
3
+ *
4
+ * @packageDocumentation
5
+ * @module Heartbeat
6
+ */
7
+ import type { Channel } from "../channel/types.js";
8
+ import type { HeartbeatPongParams } from "../protocol/reserved-types.js";
9
+ import { EventEmitter } from "../utils/events.js";
10
+ import type { HeartbeatOptions, HeartbeatState, HeartbeatEventMap } from "./types.js";
11
+ /**
12
+ * Manages heartbeat ping/pong cycle to detect unresponsive workers.
13
+ *
14
+ * The HeartbeatManager sends periodic `__heartbeat_ping__` notifications via the
15
+ * control channel and expects `__heartbeat_pong__` responses within the configured
16
+ * timeout. After `maxMissed` consecutive missed pongs, the worker is declared dead.
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * const heartbeat = new HeartbeatManager(controlChannel, {
21
+ * interval: 30000,
22
+ * timeout: 5000,
23
+ * maxMissed: 3,
24
+ * });
25
+ *
26
+ * heartbeat.on('heartbeat:pong', ({ latencyMs }) => {
27
+ * console.log(`Pong received with ${latencyMs}ms latency`);
28
+ * });
29
+ *
30
+ * heartbeat.on('heartbeat:dead', ({ missedCount }) => {
31
+ * console.log(`Worker dead after ${missedCount} missed pongs`);
32
+ * // Trigger restart or cleanup
33
+ * });
34
+ *
35
+ * heartbeat.start();
36
+ *
37
+ * // When done
38
+ * heartbeat.stop();
39
+ * ```
40
+ */
41
+ export declare class HeartbeatManager extends EventEmitter<HeartbeatEventMap> {
42
+ private readonly options;
43
+ private readonly channel;
44
+ private state;
45
+ private intervalHandle;
46
+ private timeoutHandle;
47
+ /**
48
+ * Creates a new HeartbeatManager.
49
+ *
50
+ * @param channel - Control channel to send heartbeat notifications on
51
+ * @param options - Configuration options (merged with defaults)
52
+ */
53
+ constructor(channel: Channel, options?: Partial<HeartbeatOptions>);
54
+ /**
55
+ * Start heartbeat monitoring.
56
+ * Sends first ping immediately, then at configured interval.
57
+ */
58
+ start(): void;
59
+ /**
60
+ * Stop heartbeat monitoring.
61
+ * Clears all timers and resets counters for clean restart.
62
+ */
63
+ stop(): void;
64
+ /**
65
+ * Call when any activity occurs on the channel.
66
+ * If implicitHeartbeat is enabled, resets the missed counter, clears pending ping,
67
+ * and emits heartbeat:recovered if the worker was previously considered unhealthy.
68
+ */
69
+ onActivity(): void;
70
+ /**
71
+ * Handle incoming pong notification.
72
+ * Should be called by the channel when `__heartbeat_pong__` is received.
73
+ *
74
+ * @param params - The pong notification parameters
75
+ */
76
+ handlePong(params: HeartbeatPongParams): void;
77
+ /**
78
+ * Get current heartbeat state (readonly).
79
+ */
80
+ getState(): Readonly<HeartbeatState>;
81
+ /**
82
+ * Get current options (readonly).
83
+ */
84
+ getOptions(): Readonly<Required<HeartbeatOptions>>;
85
+ /**
86
+ * Check if heartbeat is currently running.
87
+ */
88
+ isRunning(): boolean;
89
+ /**
90
+ * Reset state for restart scenarios.
91
+ * Clears timers and resets all counters.
92
+ */
93
+ reset(): void;
94
+ /**
95
+ * Sends a heartbeat ping notification.
96
+ */
97
+ private sendPing;
98
+ /**
99
+ * Handles a missed pong (timeout or send failure).
100
+ */
101
+ private handleMissed;
102
+ /**
103
+ * Clears all active timers.
104
+ */
105
+ private clearTimers;
106
+ }
107
+ //# sourceMappingURL=manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/heartbeat/manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAuB,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AAC9F,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,gBAAgB,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEtF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,iBAAiB,CAAC;IACnE,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA6B;IACrD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,KAAK,CAMX;IAEF,OAAO,CAAC,cAAc,CAA+C;IACrE,OAAO,CAAC,aAAa,CAA8C;IAEnE;;;;;OAKG;gBACS,OAAO,EAAE,OAAO,EAAE,OAAO,GAAE,OAAO,CAAC,gBAAgB,CAAM;IAMrE;;;OAGG;IACH,KAAK,IAAI,IAAI;IAiBb;;;OAGG;IACH,IAAI,IAAI,IAAI;IAYZ;;;;OAIG;IACH,UAAU,IAAI,IAAI;IA2BlB;;;;;OAKG;IACH,UAAU,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAmC7C;;OAEG;IACH,QAAQ,IAAI,QAAQ,CAAC,cAAc,CAAC;IAIpC;;OAEG;IACH,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAIlD;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,KAAK,IAAI,IAAI;IAWb;;OAEG;IACH,OAAO,CAAC,QAAQ;IA2BhB;;OAEG;IACH,OAAO,CAAC,YAAY;IA2BpB;;OAEG;IACH,OAAO,CAAC,WAAW;CAUpB"}