public static OrderWithStatus FromOrder(Order order)
        {
            if (order == null)
            {
                return(null);
            }

            // To simulate a real backend process, we fake status updates based on the amount
            // of time since the order was placed
            string        statusText;
            List <Marker> mapMarkers;
            var           dispatchTime     = order.CreatedTime.AddSeconds(10);
            var           deliveryDuration = TimeSpan.FromMinutes(1); // Unrealistic, but more interesting to watch
            int           progress         = 0;

            if (DateTime.UtcNow < dispatchTime)
            {
                statusText = "Preparing";
                progress   = 33;
                mapMarkers = new List <Marker>
                {
                    ToMapMarker("You", order.DeliveryLocation, showPopup: true)
                };
            }
            else if (DateTime.UtcNow < dispatchTime + deliveryDuration)
            {
                statusText = "Out for delivery";
                progress   = 66;

                var startPosition = ComputeStartPosition(order);
                var proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / deliveryDuration.TotalMilliseconds);
                var driverPosition = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);
                mapMarkers = new List <Marker>
                {
                    ToMapMarker("You", order.DeliveryLocation),
                    ToMapMarker("Driver", driverPosition, showPopup: true),
                };
            }
            else
            {
                statusText = "Delivered";
                progress   = 100;
                mapMarkers = new List <Marker>
                {
                    ToMapMarker("Delivery location", order.DeliveryLocation, showPopup: true),
                };
            }

            return(new OrderWithStatus
            {
                Order = order,
                StatusText = statusText,
                MapMarkers = mapMarkers,
                Progress = progress
            });
        }
Пример #2
0
        private async Task ProcessAsync(Order order)
        {
            var database   = multiplexer.GetDatabase();
            var subscriber = multiplexer.GetSubscriber();
            var status     = new OrderStatus()
            {
                Id              = order.OrderId,
                Status          = "Preparing",
                CurrentLocation = null,
            };

            await database.StringSetAsync($"orderstatus-{order.OrderId}", JsonSerializer.Serialize(status, options));

            await subscriber.PublishAsync($"orderupdates-{order.OrderId}", JsonSerializer.Serialize(status, options));

            await Task.Delay(TimeSpan.FromSeconds(10));

            var startPosition = ComputeStartPosition(order);

            status.Status          = "Out for delivery";
            status.CurrentLocation = startPosition;

            await database.StringSetAsync($"orderstatus-{order.OrderId}", JsonSerializer.Serialize(status, options));

            await subscriber.PublishAsync($"orderupdates-{order.OrderId}", JsonSerializer.Serialize(status, options));

            var stopwatch = Stopwatch.StartNew();
            var duration  = TimeSpan.FromMinutes(1);

            while (stopwatch.Elapsed < duration)
            {
                var proportionOfDeliveryCompleted = Math.Min(1, stopwatch.Elapsed.TotalMilliseconds / duration.TotalMilliseconds);
                status.CurrentLocation = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);

                await database.StringSetAsync($"orderstatus-{order.OrderId}", JsonSerializer.Serialize(status, options));

                await subscriber.PublishAsync($"orderupdates-{order.OrderId}", JsonSerializer.Serialize(status, options));

                await Task.Delay(TimeSpan.FromSeconds(3));
            }

            status.Status = "Delivered";
            await database.StringSetAsync($"orderstatus-{order.OrderId}", JsonSerializer.Serialize(status, options));

            await subscriber.PublishAsync($"orderupdates-{order.OrderId}", JsonSerializer.Serialize(status, options));

            logger.LogInformation("Delivered order {OrderId}.", order.OrderId);
        }
Пример #3
0
    public static OrderWithStatus FromOrder(Order order)
    {
        // To simulate a real backend process, we fake status updates based on the amount
        // of time since the order was placed
        string        statusText;
        List <Marker> mapMarkers;
        var           dispatchTime = order.CreatedTime.Add(PreparationDuration);

        if (DateTime.Now < dispatchTime)
        {
            statusText = "Preparing";
            mapMarkers = new List <Marker>
            {
                ToMapMarker("You", order.DeliveryLocation, showPopup: true)
            };
        }
        else if (DateTime.Now < dispatchTime + DeliveryDuration)
        {
            statusText = "Out for delivery";

            var startPosition = ComputeStartPosition(order);
            var proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / DeliveryDuration.TotalMilliseconds);
            var driverPosition = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);
            mapMarkers = new List <Marker>
            {
                ToMapMarker("You", order.DeliveryLocation),
                ToMapMarker("Driver", driverPosition, showPopup: true),
            };
        }
        else
        {
            statusText = "Delivered";
            mapMarkers = new List <Marker>
            {
                ToMapMarker("Delivery location", order.DeliveryLocation, showPopup: true),
            };
        }

        return(new OrderWithStatus
        {
            Order = order,
            StatusText = statusText,
            MapMarkers = mapMarkers,
        });
    }
Пример #4
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Pizza delivery worker running at: {time}", DateTimeOffset.Now);
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var msg = await PizzaDeliveryQueue.GetMessageAsync();

                    if (msg != null)
                    {
                        var order = JsonConvert.DeserializeObject <Order>(msg.AsString);

                        using (IServiceScope scope = _serviceProvider.CreateScope())
                        {
                            // Save the order to the DB
                            var context = scope.ServiceProvider.GetRequiredService <PizzaStoreContext>();
                            order.Status = "Out for delivery";
                            context.Orders.Attach(order);
                            await context.SaveChangesAsync();

                            await PizzaDeliveryQueue.DeleteMessageAsync(msg);

                            _logger.LogInformation($"Order {order.OrderId} out for delivery");

                            // Send delivery status
                            var startPosition    = order.CurrentLocation;
                            var dispatchTime     = DateTime.Now;
                            var deliveryDuration = TimeSpan.FromSeconds(20);
                            var proportionOfDeliveryCompleted = 0d;
                            var httpClient = new HttpClient {
                                BaseAddress = new Uri("https://localhost:5001")
                            };
                            var client = GrpcClient.Create <PizzaOrderStatusClient>(httpClient);
                            Ack ack;

                            while (proportionOfDeliveryCompleted < 1)
                            {
                                proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / deliveryDuration.TotalMilliseconds);
                                _logger.LogInformation($"Proportion complete for order {order.OrderId}: {proportionOfDeliveryCompleted}");
                                order.CurrentLocation = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);

                                ack = await client.SendStatusAsync(order.ToStatusUpdate());

                                _logger.LogInformation($"Status update ack: {ack.Message}");

                                await Task.Delay(1000, stoppingToken);
                            }

                            order.Status = "Delivered";
                            context.Orders.Attach(order);
                            await context.SaveChangesAsync();

                            _logger.LogInformation($"Order {order.OrderId} delivered");

                            ack = await client.SendStatusAsync(order.ToStatusUpdate());

                            _logger.LogInformation($"Status update ack: {ack.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"Error deliverying pizza order: {ex.Message}");
                }

                // Mandatory Pizza delivery worker break
                await Task.Delay(1000, stoppingToken);
            }
        }
Пример #5
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("Pizza delivery worker running at: {time}", DateTimeOffset.Now);
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    var msg = await PizzaDeliveryQueue.GetMessageAsync();

                    if (msg != null)
                    {
                        var order = JsonConvert.DeserializeObject <Order>(msg.AsString);

                        using (IServiceScope scope = _serviceProvider.CreateScope())
                        {
                            // Save the order to the DB
                            var context = scope.ServiceProvider.GetRequiredService <PizzaStoreContext>();
                            order.Status = "Out for delivery";
                            context.Orders.Attach(order);
                            var result = await context.SaveChangesAsync();

                            await PizzaDeliveryQueue.DeleteMessageAsync(msg);

                            _logger.LogInformation($"Order {order.RequestId} out for delivery");

                            // Send delivery status
                            var                    startPosition    = order.CurrentLocation;
                            var                    dispatchTime     = DateTime.Now;
                            var                    deliveryDuration = TimeSpan.FromSeconds(20);
                            var                    proportionOfDeliveryCompleted = 0d;
                            StatusUpdate           statusUpdate = order.ToStatusUpdate();
                            PizzaOrderStatusClient client       = default;
                            HttpClient             httpClient   = default;
                            Ack                    ack          = default;
                            var                    httpHandler  = new HttpClientHandler();
                            // Return `true` to allow certificates that are untrusted/invalid
                            httpHandler.ServerCertificateCustomValidationCallback =
                                HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
                            httpHandler.UseProxy = false;
                            while (proportionOfDeliveryCompleted == 0d)
                            {
                                if (DateTime.Now > dispatchTime.Add(deliveryDuration))
                                {
                                    proportionOfDeliveryCompleted -= 1;
                                }
                            }
                            {
                                proportionOfDeliveryCompleted = Math.Min(1, (DateTime.Now - dispatchTime).TotalMilliseconds / deliveryDuration.TotalMilliseconds);
                                _logger.LogInformation($"Proportion complete for order {order.RequestId}: {proportionOfDeliveryCompleted}");
                                order.CurrentLocation = LatLong.Interpolate(startPosition, order.DeliveryLocation, proportionOfDeliveryCompleted);

                                var channel = GrpcChannel.ForAddress("https://localhost:54001/",
                                                                     new GrpcChannelOptions {
                                    HttpHandler = httpHandler
                                });
                                client = new PizzaOrderStatusClient(channel);

                                //httpClient = new HttpClient { BaseAddress = new Uri(UriString) };

                                //httpClient.Timeout = new TimeSpan(0, 3, 0);
                                //client = GrpcClient.Create<PizzaOrderStatusClient>(httpClient);
                                ack = await client.SendStatusAsync(statusUpdate);


                                _logger.LogInformation($"Status update ack: {ack.Message}");

                                await Task.Delay(1000, stoppingToken);
                            }

                            order.Status = "Delivered";
                            context.Orders.Attach(order);
                            await context.SaveChangesAsync();

                            _logger.LogInformation($"Order {order.RequestId} delivered");

                            ack = await client.SendStatusAsync(order.ToStatusUpdate());

                            _logger.LogInformation($"Status update ack: {ack.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, $"Error deliverying pizza order: {ex.Message}");
                }

                // Mandatory Pizza delivery worker break
                await Task.Delay(1000, stoppingToken);
            }
        }