public void TransactionCoordinator_should_forward_transaction_init_to_all_participants() { var p1 = ActorOf(config => config.Receive<TransactionCoordinator.BeginTransaction>((transaction, context) => TestActor.Forward(transaction))); var p2 = ActorOf(config => config.Receive<TransactionCoordinator.BeginTransaction>((transaction, context) => TestActor.Forward(transaction))); var beginTransaction = new TransactionCoordinator.BeginTransaction(_transactionId, new[] { p1, p2 }, null); _transaction.Tell(beginTransaction); ExpectMsg<TransactionCoordinator.BeginTransaction>(e => e.TransactionId == _transactionId); ExpectMsg<TransactionCoordinator.BeginTransaction>(e => e.TransactionId == _transactionId); ExpectNoMsg(); }
public void TransactionCoordinator_after_receiving_continue_from_all_participants_should_send_commit() { Action<IActorDsl> configure = config => { config.Receive<TransactionCoordinator.BeginTransaction>((transaction, context) => context.Sender.Tell(new TransactionCoordinator.Continue(transaction.TransactionId))); config.Receive<TransactionCoordinator.Commit>((commit, context) => TestActor.Forward(commit)); }; var p1 = ActorOf(configure); var p2 = ActorOf(configure); var beginTransaction = new TransactionCoordinator.BeginTransaction(_transactionId, new[] { p1, p2 }, null); _transaction.Tell(beginTransaction); ExpectMsg<TransactionCoordinator.Commit>(e => e.TransactionId == _transactionId); ExpectMsg<TransactionCoordinator.Commit>(e => e.TransactionId == _transactionId); ExpectNoMsg(); }
public void TransactionCoordinator_after_receiving_any_abort_should_send_rollback() { var p1 = ActorOf(config => { config.Receive<TransactionCoordinator.BeginTransaction>((transaction, context) => context.Sender.Tell(new TransactionCoordinator.Continue(transaction.TransactionId))); config.Receive<TransactionCoordinator.Commit>((commit, context) => TestActor.Forward(commit)); config.Receive<TransactionCoordinator.Rollback>((rollback, context) => TestActor.Forward(rollback)); }); var p2 = ActorOf(config => { config.Receive<TransactionCoordinator.BeginTransaction>((transaction, context) => context.Sender.Tell(new TransactionCoordinator.Abort(transaction.TransactionId, new Exception("boom")))); config.Receive<TransactionCoordinator.Commit>((commit, context) => TestActor.Forward(commit)); config.Receive<TransactionCoordinator.Rollback>((rollback, context) => TestActor.Forward(rollback)); }); var beginTransaction = new TransactionCoordinator.BeginTransaction(_transactionId, new[] { p1, p2 }, null); _transaction.Tell(beginTransaction); ExpectMsg<TransactionCoordinator.Rollback>(e => e.TransactionId == _transactionId); ExpectMsg<TransactionCoordinator.Rollback>(e => e.TransactionId == _transactionId); ExpectNoMsg(); }
/// <summary> /// Establishes first phase of the two-phase commit transaction. Current account funds are being verified. If transfer can be proceed, /// transaction goes onto pending transactions list nad <see cref="TransactionCoordinator.Commit"/> message is sent to transaction coordinator. /// Otherwise transaction is aborted. /// </summary> private void EstablishTransferTransaction(TransactionCoordinator.BeginTransaction e) { var pendingTransaction = e.Payload as PendingTransfer; if (pendingTransaction != null) { if (Self.Equals(pendingTransaction.Sender)) { // if current actor is account sender, var unreserved = State.Balance - ReservedFunds; if (pendingTransaction.Amount > 0 && pendingTransaction.Amount <= unreserved) { _pendingTransactions.Add(pendingTransaction); Sender.Tell(new TransactionCoordinator.Continue(pendingTransaction.TransactionId)); } else { Sender.Tell(new TransactionCoordinator.Abort(pendingTransaction.TransactionId, new Exception(string.Format("Account {0} has insufficient funds. Unreserved balance {1}, requested {2}", State.Id, unreserved, pendingTransaction.Amount)))); } } else if (Self.Equals(pendingTransaction.Recipient)) { // recipient's account doesn't need to check if it has enough funds _pendingTransactions.Add(pendingTransaction); Sender.Tell(new TransactionCoordinator.Commit(pendingTransaction.TransactionId)); } else { Sender.Tell(new TransactionCoordinator.Abort(e.TransactionId, new Exception(string.Format( "Transaction {0} was addressed to {1}, who is neither sender nor recipient", e.TransactionId, Self)))); Unhandled(e); } } }