This is an automated email from the ASF dual-hosted git repository.

dominikriemer pushed a commit to branch fix-plc-retry-failed-connection
in repository https://gitbox.apache.org/repos/asf/streampipes.git


The following commit(s) were added to 
refs/heads/fix-plc-retry-failed-connection by this push:
     new af6f2e1bc9 Fix connection recovery
     new 423a21a7c6 Merge branch 'fix-plc-retry-failed-connection' of 
github.com:apache/streampipes into fix-plc-retry-failed-connection
af6f2e1bc9 is described below

commit af6f2e1bc9109908643440c93fe2ee308fa9e5b3
Author: Dominik Riemer <[email protected]>
AuthorDate: Mon Jun 22 10:16:48 2026 +0200

    Fix connection recovery
---
 .../plc/cache/SpConnectionContainer.java           | 50 +++++++++++-----------
 .../plc/adapter/ConnectionContainerReproTest.java  | 39 +++++++++++++++++
 2 files changed, 63 insertions(+), 26 deletions(-)

diff --git 
a/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/cache/SpConnectionContainer.java
 
b/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/cache/SpConnectionContainer.java
index 67eda0f222..ec1f0371a7 100644
--- 
a/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/cache/SpConnectionContainer.java
+++ 
b/streampipes-extensions/streampipes-connectors-plc/src/main/java/org/apache/streampipes/extensions/connectors/plc/cache/SpConnectionContainer.java
@@ -169,27 +169,23 @@ public class SpConnectionContainer {
       return;
     }
 
-    // If something happened while using the connection, invalidate this one 
and create a new connection.
+    // If something happened while using the connection, invalidate it.
     if (invalidateConnection) {
       // Close the old connection.
-      try {
-        connection.close();
-      } catch (Exception e) {
-        // We're ignoring this as we have no idea, what state the connection 
is in.
-        // Nevertheless, it is polite to say something in logs about this 
situation.
-        LOGGER.warn("Exception while closing connection", e);
-      }
+      closeConnection(connection);
+      connection = null;
 
-      // Try to get a new connection.
-      try {
-        connection = connectionManager.getConnection(connectionUrl);
-      } catch (PlcConnectionException e) {
-        // If something goes wrong, close all waiting futures exceptionally.
-        LOGGER.warn("Can't get connection for {} complete queue items 
exceptionally", connectionUrl, e);
-        queue.forEach(future -> future.completeExceptionally(e));
-        queue.clear();
-        leasedConnection = null;
-        connection = null;
+      // Only reconnect immediately when another client is waiting for the 
connection.
+      if (!queue.isEmpty()) {
+        try {
+          connection = connectionManager.getConnection(connectionUrl);
+        } catch (PlcConnectionException e) {
+          // If something goes wrong, close all waiting futures exceptionally.
+          LOGGER.warn("Can't get connection for {} complete queue items 
exceptionally", connectionUrl, e);
+          queue.forEach(future -> future.completeExceptionally(e));
+          queue.clear();
+          leasedConnection = null;
+        }
       }
     }
 
@@ -197,14 +193,16 @@ public class SpConnectionContainer {
     if (queue.isEmpty()) {
       leasedConnection = null;
 
-      // Start a timer to invalidate this connection if it's idle for too long.
-      idleTimer = new Timer("CC-Idle-Timer-" + Thread.currentThread().getId());
-      idleTimer.schedule(new TimerTask() {
-        @Override
-        public void run() {
-          closeIdleConnection();
-        }
-      }, maxIdleTime.toMillis());
+      if (connection != null) {
+        // Start a timer to invalidate this connection if it's idle for too 
long.
+        idleTimer = new Timer("CC-Idle-Timer-" + 
Thread.currentThread().getId());
+        idleTimer.schedule(new TimerTask() {
+          @Override
+          public void run() {
+            closeIdleConnection();
+          }
+        }, maxIdleTime.toMillis());
+      }
       return;
     }
 
diff --git 
a/streampipes-extensions/streampipes-connectors-plc/src/test/java/org/apache/streampipes/extensions/connectors/plc/adapter/ConnectionContainerReproTest.java
 
b/streampipes-extensions/streampipes-connectors-plc/src/test/java/org/apache/streampipes/extensions/connectors/plc/adapter/ConnectionContainerReproTest.java
index a4573832b6..49decd93cd 100644
--- 
a/streampipes-extensions/streampipes-connectors-plc/src/test/java/org/apache/streampipes/extensions/connectors/plc/adapter/ConnectionContainerReproTest.java
+++ 
b/streampipes-extensions/streampipes-connectors-plc/src/test/java/org/apache/streampipes/extensions/connectors/plc/adapter/ConnectionContainerReproTest.java
@@ -265,6 +265,45 @@ class ConnectionContainerReproTest {
     connectionContainer.close();
   }
 
+  @Test
+  void doesNotEagerlyReplaceInvalidConnectionWithoutWaitingClient() throws 
Exception {
+    var firstConnection = new MutableConnection(true);
+    var secondConnection = new MutableConnection(true);
+    var managerCalls = new AtomicInteger();
+    PlcConnectionManager manager = new PlcConnectionManager() {
+      @Override
+      public PlcConnection getConnection(String url) {
+        return managerCalls.incrementAndGet() == 1 ? firstConnection : 
secondConnection;
+      }
+
+      @Override
+      public PlcConnection getConnection(String url,
+                                         PlcAuthentication authentication) {
+        return null;
+      }
+    };
+    var connectionContainer = new SpConnectionContainer(
+        manager,
+        "mock://plc",
+        Duration.ofSeconds(30),
+        Duration.ofSeconds(30),
+        url -> null
+    );
+
+    SpLeasedPlcConnection firstLease =
+        (SpLeasedPlcConnection) connectionContainer.lease().get(500, 
TimeUnit.MILLISECONDS);
+    connectionContainer.returnConnection(firstLease, true);
+
+    assertEquals(1, managerCalls.get());
+    assertEquals(1, firstConnection.closeCalls());
+
+    SpLeasedPlcConnection secondLease =
+        (SpLeasedPlcConnection) connectionContainer.lease().get(500, 
TimeUnit.MILLISECONDS);
+    assertEquals(2, managerCalls.get());
+    connectionContainer.returnConnection(secondLease, false);
+    connectionContainer.close();
+  }
+
   @Test
   void removingSlowConnectionDoesNotBlockLeasesForOtherUrls() throws Exception 
{
     var closeStarted = new CountDownLatch(1);

Reply via email to