Expire connections that have been idle too long.

The default is one hour (much less than MySQL's eight hour max idle time) but
it can be configured with `max_idle_minutes` (supplied along with the other
connection provider configuration properties).
This commit is contained in:
Michael Bayne
2026-02-14 14:22:11 -08:00
parent d27c2ff332
commit 07844dfef3
@@ -89,6 +89,7 @@ public class StaticConnectionProvider implements ConnectionProvider
public StaticConnectionProvider (Properties props) public StaticConnectionProvider (Properties props)
{ {
_props = props; _props = props;
_maxIdleMillis = Long.parseLong(props.getProperty("max_idle_minutes", "60")) * 60 * 1000L;
} }
// from ConnectionProvider // from ConnectionProvider
@@ -108,7 +109,13 @@ public class StaticConnectionProvider implements ConnectionProvider
// from ConnectionProvider // from ConnectionProvider
public void releaseConnection (String ident, boolean readOnly, Connection conn) public void releaseConnection (String ident, boolean readOnly, Connection conn)
{ {
// nothing to do here, all is well String mapkey = ident + ":" + readOnly;
Mapping conmap = _idents.get(mapkey);
if (conmap != null) {
conmap.markLastUsed();
} else {
log.warning("Unknown connection released?", "key", mapkey);
}
} }
// from ConnectionProvider // from ConnectionProvider
@@ -169,7 +176,7 @@ public class StaticConnectionProvider implements ConnectionProvider
conmap = _keys.get(key); conmap = _keys.get(key);
if (conmap == null) { if (conmap == null) {
log.debug("Creating " + key + " for " + ident + "."); log.debug("Creating " + key + " for " + ident + ".");
_keys.put(key, conmap = new Mapping(key, info, readOnly)); _keys.put(key, conmap = new Mapping(key, info, readOnly, _maxIdleMillis));
} else { } else {
log.debug("Reusing " + key + " for " + ident + "."); log.debug("Reusing " + key + " for " + ident + ".");
@@ -221,18 +228,33 @@ public class StaticConnectionProvider implements ConnectionProvider
* connection. */ * connection. */
public final String key; public final String key;
public Mapping (String key, Info info, boolean readOnly) { public Mapping (String key, Info info, boolean readOnly, long maxIdleMillis) {
this.key = key; this.key = key;
_info = info; _info = info;
_readOnly = readOnly; _readOnly = readOnly;
_maxIdleMillis = maxIdleMillis;
} }
/** Returns the main connection for this mapping, (re)opening it if necessary. */ /** Returns the main connection for this mapping, (re)opening it if necessary. */
public Connection getConnection (String ident) throws PersistenceException { public Connection getConnection (String ident) throws PersistenceException {
if (_conn == null) _conn = openConnection(ident, _info.autoCommit); long idleMillis = _lastUsed > 0 ? System.currentTimeMillis() - _lastUsed : 0L;
if (_conn != null && _maxIdleMillis > 0 && idleMillis > _maxIdleMillis) {
log.debug("Closing idle connection", "key", key, "ident", ident,
"idleMillis", idleMillis);
closeConnection(ident);
}
if (_conn == null) {
_conn = openConnection(ident, _info.autoCommit);
markLastUsed();
}
return _conn; return _conn;
} }
/** Marks the connection as having just been used. */
public void markLastUsed () {
_lastUsed = System.currentTimeMillis();
}
/** Opens and returns a new connection to this mapping's database. */ /** Opens and returns a new connection to this mapping's database. */
public Connection openConnection (String ident, Boolean autoCommit) public Connection openConnection (String ident, Boolean autoCommit)
throws PersistenceException { throws PersistenceException {
@@ -287,12 +309,17 @@ public class StaticConnectionProvider implements ConnectionProvider
protected final Info _info; protected final Info _info;
protected final boolean _readOnly; protected final boolean _readOnly;
protected final long _maxIdleMillis;
protected Connection _conn; protected Connection _conn;
protected long _lastUsed;
} }
/** Our configuration in the form of a properties object. */ /** Our configuration in the form of a properties object. */
protected Properties _props; protected Properties _props;
/** The maximum time in milliseconds a connection can remain idle before being recycled. */
protected long _maxIdleMillis;
/** A mapping from database identifier to connection records. */ /** A mapping from database identifier to connection records. */
protected HashMap<String,Mapping> _idents = new HashMap<String,Mapping>(); protected HashMap<String,Mapping> _idents = new HashMap<String,Mapping>();