public bool IsMovementPossible(Money money, CreditTransactionType creditTransactionType) { Money currentBalance = GetBalance(); Money balanceAfterMovement = new Transaction(money, creditTransactionType).GetBalanceAfterPerformed(currentBalance); return(balanceAfterMovement.Amount >= 0); }
public void MakeMovement(Money money, CreditTransactionType creditTransactionType) { if (!IsMovementPossible(money, creditTransactionType)) { throw new NegativeBalanceReachedException("Balance would be negative after this transaction."); } _executedTransactions.Add(new ExecutedTransaction(money, creditTransactionType)); }
public Transaction(Money money, CreditTransactionType creditTransactionType) { Money = money; CreditTransactionType = creditTransactionType; }
public ExecutedTransaction(Money money, CreditTransactionType creditTransactionType) : base(money, creditTransactionType) { MovementDate = DateTime.UtcNow; }
public Task <TransactionAttempt> ExecuteTransaction(Guid transactionIdentifier, Player player, Money money, CreditTransactionType creditTransactionType) { bool isMovementPossible = player.Wallet.IsMovementPossible(money, creditTransactionType); TransactionState transactionResult; if (isMovementPossible) { player.Wallet.MakeMovement(money, creditTransactionType); transactionResult = TransactionState.Accepted; } else { transactionResult = TransactionState.Rejected; } return(Task.FromResult(new TransactionAttempt(transactionIdentifier, transactionResult))); }
public async Task <Result <TransactionAttempt> > ExecuteTransaction(Guid transactionIdentifier, Player player, Money money, CreditTransactionType creditTransactionType) { bool transactionShouldBeProcessed = _transactionTasksByIdentifier.TryAdd(transactionIdentifier, new TaskCompletionSource <Result <TransactionAttempt> >()); TaskCompletionSource <Result <TransactionAttempt> > transactionInProgress = _transactionTasksByIdentifier[transactionIdentifier]; if (!transactionShouldBeProcessed) { return(await transactionInProgress.Task); } Result <TransactionAttempt> transaction = null; try { transaction = await _oneTransactionPerPlayerChecker.ExecuteTransaction(transactionIdentifier, player, money, creditTransactionType); } catch (Exception ex) { _transactionTasksByIdentifier.TryRemove(transactionIdentifier, out _); transaction = Result.Failure <TransactionAttempt>(ex.Message); } finally { transactionInProgress.SetResult(transaction); } return(transaction); }
public async Task <TransactionAttempt> ExecuteTransaction(Guid transactionIdentifier, Player player, Money money, CreditTransactionType creditTransactionType) { _transactionQueuePerPlayer.TryAdd(player.Identifier, new SemaphoreSlim(MaxNumberOfTransactionsPerPlayer, MaxNumberOfTransactionsPerPlayer)); SemaphoreSlim semaphoreForTransactionProcessingPerPlayer = _transactionQueuePerPlayer[player.Identifier]; await semaphoreForTransactionProcessingPerPlayer.WaitAsync(); try { return(await _transactionDomainLogicExecutor.ExecuteTransaction(transactionIdentifier, player, money, creditTransactionType)); } finally { semaphoreForTransactionProcessingPerPlayer.Release(); } }