/// <remarks>
        ///     Конечно же, если выберется такая проверка, то её лучше вынести в отдельный сервис, потому-что контроллер не должен
        ///     быть таким умным и многофункциональным.
        ///     Тут баланс между скоростью работы сервиса IFiguresStorage/ его нагруженностью / средним колличеством позиций
        ///     Ну и если позиций мало, сервис работает быстро, то этот метод лучше не использовать, так как генерация исключения
        ///     операция не дешёвая
        /// </remarks>
        // TODO: вынести в отлельный сервис
        private bool AreAllPositionsAvailableFast(Cart cart, out Position badPosition)
        {
            var cts = new CancellationTokenSource();

            Position badPositionLocal = null;

            try
            {
                cart.Positions.AsParallel().WithCancellation(cts.Token).ForAll(position =>
                {
                    // Если нашли недоступную позицию - отменяем все проверки (неплохо бы добавить CancellationToken и в IFiguresStorage)
                    if (!_figuresStorage.CheckIfAvailable(position.Type, position.Count))
                    {
                        badPositionLocal = position;

                        cts.Cancel();
                    }
                });
            }
            catch (OperationCanceledException)
            {
                return(false);
            }
            catch (AggregateException e)
            {
                // Что-то пошло не так рушим всё и сразу
                // Перед тем как пробросить эксепшен - логируем
                _logger.Log(LogLevel.Error, e, e.Message);

                // Именно так, чтобы сохранить полный stack trace
                throw;
            }
            finally
            {
                badPosition = badPositionLocal;

                cts.Dispose();
            }

            return(true);
        }
Ejemplo n.º 2
0
        public async Task <decimal> OrderFigures(Cart cart)
        {
            Order order = new Order
            {
                Positions = cart.Positions.Select(x => new OrderFigure(x)).ToList()
            };

            order.Positions.ForEach(x => x.Figure.Validate());

            cart.Positions.ForEach(x =>
            {
                if (_figuresStorage.CheckIfAvailable(x.Type, x.Count))
                {
                    throw new FigureNotAvailableException();
                }
            });

            cart.Positions.ForEach(x => _figuresStorage.Reserve(x.Type, x.Count));

            return(await _orderStorage.Save(order));
        }