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();
        }
Ejemplo n.º 4
0
        /// <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);
                }
            }
        }