Have the depot retry on transient failures.
Untested, until tomorrow morning!
This commit is contained in:
@@ -85,18 +85,7 @@ public class PersistenceContext
|
|||||||
throws PersistenceException
|
throws PersistenceException
|
||||||
{
|
{
|
||||||
// TODO: check the cache using query.getKey()
|
// TODO: check the cache using query.getKey()
|
||||||
|
return (T) invoke(query, null, true);
|
||||||
// TODO: retry query on transient failure
|
|
||||||
Connection conn = _conprov.getConnection(_ident, true);
|
|
||||||
try {
|
|
||||||
return query.invoke(conn);
|
|
||||||
|
|
||||||
} catch (SQLException sqe) {
|
|
||||||
throw new PersistenceException("Query failure " + query, sqe);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
_conprov.releaseConnection(_ident, true, conn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,26 +96,76 @@ public class PersistenceContext
|
|||||||
{
|
{
|
||||||
// TODO: invalidate the cache using the modifier's key
|
// TODO: invalidate the cache using the modifier's key
|
||||||
|
|
||||||
// TODO: retry query on transient failure
|
int result = (Integer) invoke(null, modifier, true);
|
||||||
Connection conn = _conprov.getConnection(_ident, false);
|
// TODO: (optionally) cache the results of the modifier
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal invoke method that takes care of transient retries
|
||||||
|
* for both queries and modifiers.
|
||||||
|
*/
|
||||||
|
protected <T> Object invoke (
|
||||||
|
Query<T> query, Modifier modifier, boolean retryOnTransientFailure)
|
||||||
|
throws PersistenceException
|
||||||
|
{
|
||||||
|
boolean isReadOnlyQuery = (query != null);
|
||||||
|
Connection conn = _conprov.getConnection(_ident, isReadOnlyQuery);
|
||||||
try {
|
try {
|
||||||
int result = modifier.invoke(conn);
|
if (isReadOnlyQuery) {
|
||||||
// TODO: (optionally) cache the results of the modifier
|
// if this becomes more complex than this single statement,
|
||||||
return result;
|
// then this should turn into a method call that contains
|
||||||
|
// the complexity
|
||||||
|
return query.invoke(conn);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// if this becomes more complex than this single statement,
|
||||||
|
// then this should turn into a method call that contains
|
||||||
|
// the complexity
|
||||||
|
return modifier.invoke(conn);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (SQLException sqe) {
|
} catch (SQLException sqe) {
|
||||||
// convert this exception to a DuplicateKeyException if appropriate
|
|
||||||
String msg = sqe.getMessage();
|
if (!isReadOnlyQuery) {
|
||||||
if (msg != null && msg.indexOf("Duplicate entry") != -1) {
|
// convert this exception to a DuplicateKeyException if
|
||||||
throw new DuplicateKeyException(msg);
|
// appropriate
|
||||||
|
String msg = sqe.getMessage();
|
||||||
|
if (msg != null && msg.indexOf("Duplicate entry") != -1) {
|
||||||
|
throw new DuplicateKeyException(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retryOnTransientFailure && isTransientException(sqe)) {
|
||||||
|
Log.info("Transient failure executing operation, " +
|
||||||
|
"retrying [error=" + sqe + "].");
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
throw new PersistenceException(
|
String msg = isReadOnlyQuery ? "Query failure " + query
|
||||||
"Modifier failure " + modifier, sqe);
|
: "Modifier failure " + modifier;
|
||||||
|
throw new PersistenceException(msg, sqe);
|
||||||
}
|
}
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
_conprov.releaseConnection(_ident, false, conn);
|
_conprov.releaseConnection(_ident, isReadOnlyQuery, conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if we got here, we want to retry a transient failure
|
||||||
|
return invoke(query, modifier, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the specified exception is a transient failure
|
||||||
|
* that can be retried.
|
||||||
|
*/
|
||||||
|
protected boolean isTransientException (SQLException sqe)
|
||||||
|
{
|
||||||
|
// TODO: this is MySQL specific. This was snarfed from MySQLLiaison.
|
||||||
|
String msg = sqe.getMessage();
|
||||||
|
return (msg != null &&
|
||||||
|
(msg.indexOf("Lost connection") != -1 ||
|
||||||
|
msg.indexOf("link failure") != -1 ||
|
||||||
|
msg.indexOf("Broken pipe") != -1));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String _ident;
|
protected String _ident;
|
||||||
|
|||||||
Reference in New Issue
Block a user