private async Task <int> ProcessBatchSettleTransactionsAsync(BatchSettle request, ConcurrentBag <BatchCommandTransactionError> errorsList)
        {
            var txCount    = 0;
            var brands     = new ConcurrentDictionary <string, Brand>();
            var userGroups = request.Transactions.GroupBy(x => x.UserId);

            await Task.WhenAll(
                userGroups.Select(userTransactions =>
                                  Task.Run(async() =>
            {
                var commands = _container.Resolve <IGameCommands>();

                foreach (var transaction in userTransactions)
                {
                    try
                    {
                        var betData = new GameActionData
                        {
                            RoundId = transaction.RoundId,
                            TransactionReferenceId = transaction.ReferenceId,
                            ExternalTransactionId  = transaction.Id,
                            Amount       = transaction.Amount,
                            CurrencyCode = transaction.CurrencyCode,
                            Description  = transaction.Description,
                            BatchId      = request.BatchId,
                        };

                        switch (transaction.TransactionType)
                        {
                        case BatchSettleBetTransactionType.Win:
                            await commands.WinBetAsync(betData, Context);
                            break;

                        case BatchSettleBetTransactionType.Lose:
                            await commands.LoseBetAsync(betData, Context);
                            break;

                        case BatchSettleBetTransactionType.Free:
                            await commands.FreeBetAsync(betData, Context);
                            break;

                        case BatchSettleBetTransactionType.Tie:
                            await commands.TieBetAsync(betData, Context);
                            break;
                        }

                        Interlocked.Increment(ref txCount);
                    }
                    catch (Exception ex)
                    {
                        errorsList.Add(CreateBatchTransactionError(ex, transaction.Id, transaction.UserId));
                    }
                }
            })));

            return(txCount);
        }
        async Task <BatchSettleResponse> ICommonGameActionsProvider.BatchSettle(BatchSettle request)
        {
            var errorCode        = GameApiErrorCode.NoError;
            var errorDescription = (string)null;
            var errorsList       = new ConcurrentBag <BatchCommandTransactionError>();
            var txCount          = 0;
            var isDuplicateBatch = 0;
            var timer            = new Stopwatch();
            var playerBalances   = new Dictionary <Guid, decimal>();

            timer.Start();
            try
            {
                _gameQueries.ValidateBatchIsUnique(request.BatchId, Context.GameProviderId);

                if (false == await _gameQueries.ValidateSecurityKey(Context.GameProviderId, request.SecurityKey))
                {
                    throw new ArgumentException("Invalid security key.");
                }

                txCount = await ProcessBatchSettleTransactionsAsync(request, errorsList);

                playerBalances = _gameQueries.GetPlayableBalances(request.Transactions.Select(x => x.UserId));
            }
            catch (DuplicateBatchException ex)
            {
                isDuplicateBatch = 1;
                errorCode        = _errors.GetErrorCodeByException(ex, out errorDescription);
            }
            catch (Exception ex)
            {
                errorCode = _errors.GetErrorCodeByException(ex, out errorDescription);
            }

            timer.Stop();

            return(new BatchSettleResponse
            {
                BatchId = request.BatchId,
                TransactionCount = txCount,
                BatchTimestamp = DateTimeOffset.UtcNow.ToString("O"),
                Elapsed = timer.ElapsedMilliseconds,
                Errors = errorsList.ToList(),
                ErrorCode = errorCode,
                ErrorDescription = errorDescription,
                IsDuplicate = isDuplicateBatch,
                PlayerBalances = new Dictionary <Guid, decimal>(playerBalances)
            });
        }
 public async Task <BatchSettleResponse> Post(BatchSettle request)
 {
     return(await GameActions.BatchSettle(request));
 }