use of com.torodb.mongodb.repl.oplogreplier.OplogOperationApplier.OplogApplyingException in project torodb by torodb.
the class SimpleAnalyzedOplogBatchExecutorTest method testVisit_SingleOp_OplogApplyingEx.
@Test
public void testVisit_SingleOp_OplogApplyingEx() throws Exception {
//GIVEN
OplogOperation operation = mock(OplogOperation.class);
SingleOpAnalyzedOplogBatch batch = new SingleOpAnalyzedOplogBatch(operation);
ApplierContext applierContext = new ApplierContext.Builder().setReapplying(true).setUpdatesAsUpserts(true).build();
Timer timer = mock(Timer.class);
Context context = mock(Context.class);
given(metrics.getSingleOpTimer(operation)).willReturn(timer);
given(timer.time()).willReturn(context);
doThrow(new OplogApplyingException(new MongoException(ErrorCode.BAD_VALUE))).when(executor).execute(operation, applierContext);
//WHEN
try {
executor.visit(batch, applierContext);
fail("An exception was expected");
} catch (RetrierGiveUpException | RetrierAbortException ignore) {
}
//THEN
then(metrics).should().getSingleOpTimer(operation);
then(timer).should().time();
then(executor).should(times(1)).execute(operation, applierContext);
}
use of com.torodb.mongodb.repl.oplogreplier.OplogOperationApplier.OplogApplyingException in project torodb by torodb.
the class ReplSyncApplier method runProtected.
@Override
protected void runProtected() {
runThread = Thread.currentThread();
/*
* TODO: In general, the replication context can be set as not reaplying. But it is not frequent
* but possible to stop the replication after some oplog ops have been apply but not marked as
* executed on the oplog manager. For that reason, all oplog ops betwen the last operation that
* have been marked as applyed and the current last operation on the remote oplog must be
* executed as replying operations. As it is not possible to do that yet, we have to always
* apply operations as replying to be safe.
*/
ApplierContext applierContext = new ApplierContext.Builder().setReapplying(true).setUpdatesAsUpserts(true).build();
while (isRunning()) {
OplogOperation lastOperation = null;
ExclusiveWriteMongodTransaction trans = connection.openExclusiveWriteTransaction();
try (ExclusiveWriteMongodTransaction transaction = trans) {
try {
for (OplogOperation opToApply : callback.takeOps()) {
lastOperation = opToApply;
LOGGER.trace("Executing {}", opToApply);
try {
boolean done = false;
while (!done) {
try {
oplogOpApplier.apply(opToApply, transaction, applierContext);
transaction.commit();
done = true;
} catch (RollbackException ex) {
LOGGER.debug("Recived a rollback exception while applying an oplog op", ex);
}
}
} catch (OplogApplyingException ex) {
if (!callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because one operation " + "cannot be executed", ex);
break;
}
} catch (UserException ex) {
if (callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because one operation " + "cannot be executed", ex);
break;
}
} catch (Throwable ex) {
if (callback.failedToApply(opToApply, ex)) {
LOGGER.error(serviceName() + " stopped because " + "an unknown error", ex);
break;
}
}
callback.markAsApplied(opToApply);
}
} catch (InterruptedException ex) {
LOGGER.debug("Interrupted applier thread while applying an operator");
}
}
if (lastOperation != null) {
try (WriteOplogTransaction oplogTransaction = oplogManager.createWriteTransaction()) {
oplogTransaction.addOperation(lastOperation);
} catch (OplogManagerPersistException ex) {
if (callback.failedToApply(lastOperation, ex)) {
LOGGER.error(serviceName() + " stopped because " + "the last applied operation couldn't " + "be persisted", ex);
break;
}
}
}
}
}
Aggregations