From 93dc2ca1d58a8b4683f332419902055bc1b7c406 Mon Sep 17 00:00:00 2001 From: reluc Date: Fri, 24 Nov 2023 17:46:22 +0100 Subject: [PATCH 1/2] fix(binding-modbus/modbus-connection): clean up operations when timeout If we don't clean up the queue and the application is looping trying to read modbus registers, the queue will grow indefinitely. This cleans up the queue when a timeout occurs (e.g. wrong remote host or not reachable). --- packages/binding-modbus/src/modbus-connection.ts | 12 +++++++----- .../binding-modbus/test/modbus-connection-test.ts | 3 +++ 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/binding-modbus/src/modbus-connection.ts b/packages/binding-modbus/src/modbus-connection.ts index 86f6cc92b..33e25dff0 100644 --- a/packages/binding-modbus/src/modbus-connection.ts +++ b/packages/binding-modbus/src/modbus-connection.ts @@ -282,12 +282,14 @@ export class ModbusConnection { this.trigger(); } catch (error) { warn("Cannot reconnect to modbus server"); - // inform all the operations that the connection cannot be recovered - this.queue.forEach((transaction) => { - transaction.operations.forEach((op) => { - op.failed(error instanceof Error ? error : new Error(JSON.stringify(error))); + // inform and clean up all the operations that the connection cannot be recovered + do { + const transaction = this.queue.shift(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- queue.length > 0 + transaction!.operations.forEach((operation) => { + operation.failed(error instanceof Error ? error : new Error(JSON.stringify(error))); }); - }); + } while (this.queue.length > 0); } } else if (this.client.isOpen && this.currentTransaction == null && this.queue.length > 0) { // take next transaction from queue and execute diff --git a/packages/binding-modbus/test/modbus-connection-test.ts b/packages/binding-modbus/test/modbus-connection-test.ts index b6f54c518..3f0562b7f 100644 --- a/packages/binding-modbus/test/modbus-connection-test.ts +++ b/packages/binding-modbus/test/modbus-connection-test.ts @@ -82,6 +82,8 @@ describe("Modbus connection", () => { connection.enqueue(op); await op.execute().should.eventually.be.rejected; + connection.queue.length.should.equal(0); + connection.close(); }).timeout(5000); @@ -105,6 +107,7 @@ describe("Modbus connection", () => { connection.enqueue(op); await op.execute().should.eventually.be.rejected; + connection.queue.length.should.equal(0); connection.close(); }).timeout(5000); From 96ee5437b6c64260d23355ab3be24dad11236750 Mon Sep 17 00:00:00 2001 From: reluc Date: Wed, 29 Nov 2023 11:27:48 +0100 Subject: [PATCH 2/2] fixup! fix(binding-modbus/modbus-connection): clean up operations when timeout If we don't clean up the queue and the application is looping trying to read modbus registers, the queue will grow indefinitely. This cleans up the queue when a timeout occurs (e.g. wrong remote host or not reachable). --- packages/binding-modbus/src/modbus-connection.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/binding-modbus/src/modbus-connection.ts b/packages/binding-modbus/src/modbus-connection.ts index 33e25dff0..11509e55f 100644 --- a/packages/binding-modbus/src/modbus-connection.ts +++ b/packages/binding-modbus/src/modbus-connection.ts @@ -283,13 +283,13 @@ export class ModbusConnection { } catch (error) { warn("Cannot reconnect to modbus server"); // inform and clean up all the operations that the connection cannot be recovered - do { + while (this.queue.length > 0) { const transaction = this.queue.shift(); // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- queue.length > 0 transaction!.operations.forEach((operation) => { operation.failed(error instanceof Error ? error : new Error(JSON.stringify(error))); }); - } while (this.queue.length > 0); + } } } else if (this.client.isOpen && this.currentTransaction == null && this.queue.length > 0) { // take next transaction from queue and execute