Connection robustness improvements (#813)

* Clear heartbeat and queue when disconnected

* Give clearer error in case configure fails due to a lost connection. Used to throw 'Packet does not exist'

* If the queue processing error is due to a lost connection, throw it instead of looping endlessly

* In case we send a disconnection event we don't need to also throw

* Catch heartbeat errors

* Also handle invalid state errors

* Handle socket timeouts

* Log heartbeat failures

* Make linter happy

* Transform stream being a singleton prevented reconnection attempts

* Adapt tests to not using singleton

* Aborting already ends the connection
This commit is contained in:
Henri Bergius
2025-09-04 13:08:05 -04:00
committed by GitHub
parent dcb44d27fe
commit bcdda8b751
11 changed files with 124 additions and 54 deletions
+8
View File
@@ -117,6 +117,14 @@ export class Queue {
await writer.write(item.data);
item.sent = true;
} catch (error) {
if (
error?.code === "ECONNRESET" ||
error?.code === "ERR_INVALID_STATE"
) {
writer.releaseLock();
this.lock = false;
throw error;
}
console.error(`Error sending packet ${item.id}`, error);
}
}
+15 -13
View File
@@ -1,16 +1,18 @@
/**
* Pads packets with appropriate framing information before writing to the output stream.
*/
export const toDeviceStream: TransformStream<Uint8Array, Uint8Array> =
new TransformStream<Uint8Array, Uint8Array>({
transform(chunk: Uint8Array, controller): void {
const bufLen = chunk.length;
const header = new Uint8Array([
0x94,
0xc3,
(bufLen >> 8) & 0xff,
bufLen & 0xff,
]);
controller.enqueue(new Uint8Array([...header, ...chunk]));
},
});
export const toDeviceStream: () => TransformStream<Uint8Array, Uint8Array> =
() => {
return new TransformStream<Uint8Array, Uint8Array>({
transform(chunk: Uint8Array, controller): void {
const bufLen = chunk.length;
const header = new Uint8Array([
0x94,
0xc3,
(bufLen >> 8) & 0xff,
bufLen & 0xff,
]);
controller.enqueue(new Uint8Array([...header, ...chunk]));
},
});
};