This is an automated email from the ASF dual-hosted git repository. sruehl pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/plc4x.git
commit a751529f6b6885ce11d8038f35e1e3191e90ee42 Author: Sebastian Rühl <[email protected]> AuthorDate: Tue Nov 18 09:40:14 2025 +0100 fix(plc4go): speed up close of connection close --- plc4go/pkg/api/cache/PlcConnectionCache.go | 73 ++++++++++++++++++------------ 1 file changed, 43 insertions(+), 30 deletions(-) diff --git a/plc4go/pkg/api/cache/PlcConnectionCache.go b/plc4go/pkg/api/cache/PlcConnectionCache.go index 353b482211..908e5c1322 100644 --- a/plc4go/pkg/api/cache/PlcConnectionCache.go +++ b/plc4go/pkg/api/cache/PlcConnectionCache.go @@ -22,6 +22,7 @@ package cache import ( "context" "fmt" + "runtime/debug" "sync" "time" @@ -217,6 +218,7 @@ func (c *plcConnectionCache) GetConnection(ctx context.Context, connectionString } func (c *plcConnectionCache) Close() error { + ctx := context.TODO() c.log.Debug().Msg("Closing connection cache started.") c.log.Trace().Msg("Acquire lock") c.cacheLock.Lock() @@ -228,45 +230,56 @@ func (c *plcConnectionCache) Close() error { return nil } + var wg sync.WaitGroup for _, connectionContainer := range c.connections { ccLog := c.log.With().Stringer("connectionContainer", connectionContainer).Logger() ccLog.Trace().Msg("Closing connection") // Mark the connection as being closed to not try to re-establish it. connectionContainer.closed = true - // Try to get a lease as this way we kow we're not closing the connection - // while some go func is still using it. - ccLog.Trace().Msg("getting a lease") - ctx, cancel := context.WithTimeout(context.TODO(), c.maxWaitTime) - connChan, errChan := connectionContainer.lease(ctx) - select { - // We're just getting the lease as this way we can be sure nobody else is using it. - // We also really don't care if it worked, or not ... it's just an attempt of being - // nice. - case _ = <-connChan: - ccLog.Debug().Msg("Gracefully closing connection ...") - // Give back the connection. - if connectionContainer.connection != nil { - ccLog.Trace().Msg("closing actual connection") - if err := connectionContainer.connection.Close(); err != nil { - ccLog.Debug().Err(err).Msg("Error while closing connection") + wg.Go(func() { + defer func() { + if err := recover(); err != nil { + c.log.Error(). + Str("stack", string(debug.Stack())). + Interface("err", err). + Msg("panic-ed") } - } - case err := <-errChan: - ccLog.Debug().Err(err).Msg("Error while trying to get lease on connection, ignoring.") - // If we're timing out brutally kill the connection. - case <-ctx.Done(): - ccLog.Debug().Msg("Forcefully closing connection ...") - // Forcefully close this connection. - if connectionContainer.connection != nil { - if err := connectionContainer.connection.Close(); err != nil { - ccLog.Debug().Err(err).Msg("Error while closing connection") + }() + // Try to get a lease as this way we kow we're not closing the connection + // while some go func is still using it. + ccLog.Trace().Msg("getting a lease") + ctx, cancel := context.WithTimeout(ctx, c.maxWaitTime) + connChan, errChan := connectionContainer.lease(ctx) + select { + // We're just getting the lease as this way we can be sure nobody else is using it. + // We also really don't care if it worked, or not ... it's just an attempt of being + // nice. + case _ = <-connChan: + ccLog.Debug().Msg("Gracefully closing connection ...") + // Give back the connection. + if connectionContainer.connection != nil { + ccLog.Trace().Msg("closing actual connection") + if err := connectionContainer.connection.Close(); err != nil { + ccLog.Debug().Err(err).Msg("Error while closing connection") + } + } + case err := <-errChan: + ccLog.Debug().Err(err).Msg("Error while trying to get lease on connection, ignoring.") + // If we're timing out brutally kill the connection. + case <-ctx.Done(): + ccLog.Debug().Msg("Forcefully closing connection ...") + // Forcefully close this connection. + if connectionContainer.connection != nil { + if err := connectionContainer.connection.Close(); err != nil { + ccLog.Debug().Err(err).Msg("Error while closing connection") + } } } - } - cancel() - - c.log.Debug().Msg("Closing connection cache finished.") + cancel() + }) } + wg.Wait() + c.log.Debug().Msg("Closing connection cache finished.") return nil }
