Bugfix: store() should never throw a DuplicateKeyException.

It would be extremely rare, but if two nodes were trying to simultaneously
store() the same record with the same Key, one could fail with a DKE.

Attempt a second 'update' if the insert fails.
This commit is contained in:
Ray Greenwell
2013-05-07 00:03:05 +00:00
parent c63ce0c10e
commit ce3a340199
@@ -553,9 +553,12 @@ public abstract class DepotRepository
} }
final boolean[] created = new boolean[1]; final boolean[] created = new boolean[1];
try {
_ctx.invoke(new CachingModifier<T>(record, key, key) { _ctx.invoke(new CachingModifier<T>(record, key, key) {
@Override @Override
protected int invoke (Connection conn, DatabaseLiaison liaison) throws SQLException { protected int invoke (Connection conn, DatabaseLiaison liaison)
throws SQLException
{
if (_key != null) { if (_key != null) {
// run the update // run the update
int mods = builder.prepare(conn).executeUpdate(); int mods = builder.prepare(conn).executeUpdate();
@@ -590,6 +593,27 @@ public abstract class DepotRepository
stats.noteModification(pClass); stats.noteModification(pClass);
} }
}); });
} catch (DuplicateKeyException dke) {
if (key == null) {
throw dke; // how would this even happen?
}
// this should be very rare: the insert failed. Retry one more update.
_ctx.invoke(new CachingModifier<T>(record, key, key) {
@Override
protected int invoke (Connection conn, DatabaseLiaison liaison)
throws SQLException
{
builder.newQuery(update);
return builder.prepare(conn).executeUpdate();
}
@Override
public void updateStats (Stats stats) {
stats.noteModification(pClass);
}
});
}
return created[0]; return created[0];
} }