зеркало из https://github.com/Azure/reddog-code.git
348 строки
14 KiB
C#
348 строки
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net.Http;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Dapr.Client;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Microsoft.Extensions.Logging;
|
|
using RedDog.VirtualCustomers.Models;
|
|
|
|
namespace RedDog.VirtualCustomers
|
|
{
|
|
public class VirtualCustomers : BackgroundService
|
|
{
|
|
private const string OrderServiceDaprId = "order-service";
|
|
private static readonly string storeId = Environment.GetEnvironmentVariable("STORE_ID") ?? "Redmond";
|
|
public static readonly int maxItemQuantity = int.Parse(Environment.GetEnvironmentVariable("MAX_ITEM_QUANTITY") ?? "1");
|
|
public static readonly int maxUniqueItemsPerOrder = int.Parse(Environment.GetEnvironmentVariable("MAX_UNIQUE_ITEMS_PER_ORDER") ?? "10");
|
|
public static readonly int minSecondsToPlaceOrder = int.Parse(Environment.GetEnvironmentVariable("MIN_SEC_TO_PLACE_ORDER") ?? "1");
|
|
public static readonly int maxSecondsToPlaceOrder = int.Parse(Environment.GetEnvironmentVariable("MAX_SEC_TO_PLACE_ORDER") ?? "3");
|
|
public static readonly int minSecondsBetweenOrders = int.Parse(Environment.GetEnvironmentVariable("MIN_SEC_BETWEEN_ORDERS") ?? "1");
|
|
public static readonly int maxSecondsBetweenOrders = int.Parse(Environment.GetEnvironmentVariable("MAX_SEC_BETWEEN_ORDERS") ?? "3");
|
|
public static readonly int numOrders = int.Parse(Environment.GetEnvironmentVariable("NUM_ORDERS") ?? "-1");
|
|
|
|
private string DaprHttpPort = Environment.GetEnvironmentVariable("DAPR_HTTP_PORT") ?? "3500";
|
|
private IHostApplicationLifetime _lifetime;
|
|
private readonly ILogger<VirtualCustomers> _logger;
|
|
private readonly DaprClient _daprClient;
|
|
private readonly HttpClient _httpClient;
|
|
private Task _ordersTask = Task.CompletedTask;
|
|
private List<Product> _products;
|
|
private Random _random;
|
|
|
|
private static readonly (int, string, string)[] customers = {
|
|
(1,"Bruce","Wayne"),
|
|
(2,"Lou","Redwood"),
|
|
(3,"Allan","Austin"),
|
|
(4,"Rusty","Ryan"),
|
|
(5,"Aubrey","Curtis"),
|
|
(6,"Aldo","Raine"),
|
|
(7,"Magrit","Reck"),
|
|
(8,"Mason","Lucas"),
|
|
(9,"Etienne","Tremblay"),
|
|
(10,"Myrtle","Martin"),
|
|
(11,"Adelgunde","Rode"),
|
|
(12,"Matt","Wallace"),
|
|
(13,"Dick","Pepperfield"),
|
|
(14,"Beatrice","Gagnon"),
|
|
(15,"Julian","Harris"),
|
|
(16,"Ellinor","Flick"),
|
|
(17,"Nils","Rüdiger"),
|
|
(18,"Bea","Arthur"),
|
|
(19,"Mickey","O'Neil"),
|
|
(20,"Cindy","Powell"),
|
|
(21,"Brielle","Singh"),
|
|
(22,"Jackie","Moon"),
|
|
(23,"Ilhan","Kaps"),
|
|
(24,"Arthur","Grewal"),
|
|
(25,"Scarlett","Hawkins"),
|
|
(26,"Brennan","Huff"),
|
|
(27,"Marilou","Williams"),
|
|
(28,"Estelle","Getty"),
|
|
(29,"Camille","Macdonald"),
|
|
(30,"Danielle","Niemeier"),
|
|
(31,"Tom","Bishop"),
|
|
(32,"Dale","Doback"),
|
|
(33,"Logan","Scott"),
|
|
(34,"Darlene","Gregory"),
|
|
(35,"Cal","Naughton"),
|
|
(36,"Megan","Singh"),
|
|
(37,"Jeff","Goldblum"),
|
|
(38,"Cody","Chapman"),
|
|
(39,"Christina","Snyder"),
|
|
(40,"Rafi","Cunado"),
|
|
(41,"Leah","Holmes"),
|
|
(42,"Brielle","Harcourt"),
|
|
(43,"Amelia","Edwards"),
|
|
(44,"Leon","Green"),
|
|
(45,"Elizabeth","Arnold"),
|
|
(46,"Ricky","Bobby"),
|
|
(47,"Hardy","Backhaus"),
|
|
(48,"Renato","Jahnke"),
|
|
(49,"Zoe","Bélanger"),
|
|
(50,"Taco","MacArthur"),
|
|
(51,"Kelly","Harrison"),
|
|
(52,"Betty","White"),
|
|
(53,"Allen","Gamble"),
|
|
(54,"Alex","Clarke"),
|
|
(55,"Sandra","Bailey"),
|
|
(56,"Jacqueline","White"),
|
|
(57,"Erik","Lehnsherr"),
|
|
(58,"Joyce","Roberts"),
|
|
(59,"Lucille","Gutierrez"),
|
|
(60,"Ashley","Mills"),
|
|
(61,"Antoine","Thompson"),
|
|
(62,"Maddison","Hall"),
|
|
(63,"Franz","Rütten"),
|
|
(64,"Hildegund","Esch"),
|
|
(65,"Lorraine","Silva"),
|
|
(66,"Steffi","Graf"),
|
|
(67,"Amelia","Hill"),
|
|
(68,"Sophia","Williams"),
|
|
(69,"Patricia","Little"),
|
|
(70,"Peter","Weyland"),
|
|
(71,"Wanda","Simpson"),
|
|
(72,"Tyler","Durden"),
|
|
(73,"Dorothy","Mantooth"),
|
|
(74,"Sloan","Sabbath"),
|
|
(75,"Roy","Hobbs"),
|
|
(76,"Jerry","Rice"),
|
|
(77,"Christa","Ebert"),
|
|
(78,"Lily","Grewal"),
|
|
(79,"Benjamin","Perkins"),
|
|
(80,"Debra","Smith"),
|
|
(81,"Elliot","Park"),
|
|
(82,"Aubree","Williamson"),
|
|
(83,"Madison","Sanchez"),
|
|
(84,"Terry","Hoitz"),
|
|
(85,"Julie","Chavez"),
|
|
(86,"Russ","Hanneman"),
|
|
(87,"Daniel","Gagné"),
|
|
(88,"Bertram","Gilfoyle"),
|
|
(89,"Emma","Garcia"),
|
|
(90,"Leo","Spaceman"),
|
|
(91,"Clarence","Gilbert"),
|
|
(92,"Jessie","Ray"),
|
|
(93,"Kenny","Powers"),
|
|
(94,"Pippa","Wang"),
|
|
(95,"Jack","Barker"),
|
|
(96,"Jean-Baptiste","Zorg"),
|
|
(97,"Joe","Montana"),
|
|
(98,"Cathy","Perry"),
|
|
(99,"Valerie","Watkins"),
|
|
(100,"Abigail","Andersen"),
|
|
(101,"Megan","Barnaby"),
|
|
(102,"Erin","Rhodes"),
|
|
(103,"Lane","Myer"),
|
|
(104,"Charlie","Lo"),
|
|
(105,"Monique","Junot"),
|
|
(106,"Calvin","Joyner"),
|
|
(107,"Walter","White"),
|
|
(108,"Mia","Brar"),
|
|
(109,"MacKenzie","McHale"),
|
|
(110,"Ty","Webb"),
|
|
(111,"Allison","Bryant"),
|
|
(112,"Jesse","Pinkman"),
|
|
(113,"Natalie","Thompson"),
|
|
(114,"Ashley","Carlson"),
|
|
(115,"Gustavo","Fring"),
|
|
(116,"Danny","Noonan"),
|
|
(117,"Leah","Thompson"),
|
|
(118,"Elizabeth","Mitchell"),
|
|
(119,"John","McClane"),
|
|
(120,"Archer","Smith"),
|
|
(121,"Vincent","Hanna"),
|
|
(122,"Jon","Garrett"),
|
|
(123,"Dwight","Schrute"),
|
|
(124,"Vicki","Scott"),
|
|
(125,"Dwayne","Holt"),
|
|
(126,"Fletcher","Clarke"),
|
|
(127,"Grace","Cox"),
|
|
(128,"Mika","Haubold"),
|
|
(129,"Joe","Kent"),
|
|
(130,"Alexandra","Roberts"),
|
|
(131,"Will","McAvoy"),
|
|
(132,"Leo","Knight"),
|
|
(133,"Maeva","Claire"),
|
|
(134,"Keira","Martin"),
|
|
(135,"Amanda","Washington"),
|
|
(136,"Hans","Gruber"),
|
|
(137,"Judy","Gomez"),
|
|
(138,"Sergio","Ebeling"),
|
|
(139,"Quinn","Moore"),
|
|
(140,"Michael","Bolton"),
|
|
(141,"Eliza","Grant"),
|
|
(142,"Jill","Grant"),
|
|
(143,"Zoltan","Haller"),
|
|
(144,"Ramon","Ross"),
|
|
(145,"Carl","Spackler"),
|
|
(146,"Addison","Park"),
|
|
(147,"Walter","Sobchak"),
|
|
(148,"Mia","Mackay"),
|
|
(149,"Korben","Dallas"),
|
|
(150,"Milton","Waddams"),
|
|
(151,"Brent","Rodriguez"),
|
|
(152,"Melodie","Pelletier"),
|
|
(153,"Emily","Jackson"),
|
|
(154,"Neil","McCauley"),
|
|
(155,"Jessica","Lawrence"),
|
|
(156,"Julia","Lam"),
|
|
(157,"Sibilla","Knappe"),
|
|
(158,"Al","Czervik"),
|
|
(159,"Harry","Ellis"),
|
|
(160,"Emma","Williams"),
|
|
(161,"Kristen","Arnold"),
|
|
(162,"Heywood","Floyd"),
|
|
(163,"Hannah","Mackay"),
|
|
(164,"Larry","Sellers"),
|
|
(165,"Elihu","Smails"),
|
|
(166,"Cole","Trickle"),
|
|
(167,"Rita","Vrataski"),
|
|
(168,"Peter","Gibbons"),
|
|
(169,"Kayla","Smith"),
|
|
(170,"Theo","Morris"),
|
|
(171,"Edith","Carpenter"),
|
|
(172,"Sherlock","Holmes"),
|
|
(173,"David","Bowman"),
|
|
(174,"Clark","Griswold"),
|
|
(175,"Marilou","Park"),
|
|
(176,"Phil","Wenneck"),
|
|
(177,"Milan","Scholze"),
|
|
(178,"Irwin","Fletcher"),
|
|
(179,"Irene","Foster"),
|
|
(180,"Leeloo","Dallas"),
|
|
(181,"Jack","Harper"),
|
|
(182,"Jill","Lambert"),
|
|
(183,"Linda","Hunter"),
|
|
(184,"Maritta","Walch"),
|
|
(185,"Harris","Telemacher"),
|
|
(186,"Phoebe","Rice"),
|
|
(187,"Estelle","Rohrer"),
|
|
(188,"Malcolm","Beech"),
|
|
(189,"Bill","Lumberg"),
|
|
(190,"Chris","Kyle"),
|
|
(191,"Miranda","Priestly"),
|
|
(192,"Andrea","Sachs"),
|
|
(193,"Kirk","Lazarus"),
|
|
(194,"Katniss","Everdeen"),
|
|
(195,"Vinnie","Barbarino"),
|
|
(196,"Mia","Hill"),
|
|
(197,"Les","Grossman"),
|
|
(198,"Jeffrey","Lebowski"),
|
|
(199,"Wilma","Ramos"),
|
|
(200,"Rachel","Alvarez")
|
|
};
|
|
|
|
public VirtualCustomers(IHostApplicationLifetime lifetime, ILogger<VirtualCustomers> logger, DaprClient daprClient, IHttpClientFactory httpClientFactory)
|
|
{
|
|
_lifetime = lifetime;
|
|
_logger = logger;
|
|
_daprClient = daprClient;
|
|
_httpClient = httpClientFactory.CreateClient();
|
|
_random = new Random();
|
|
}
|
|
|
|
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
|
{
|
|
// try
|
|
// {
|
|
// var response = await _httpClient.GetAsync($"http://localhost:{DaprHttpPort}/v1.0/healthz", stoppingToken);
|
|
// response.EnsureSuccessStatusCode();
|
|
// }
|
|
// catch(Exception e)
|
|
// {
|
|
// _logger.LogError("Error communicating with Dapr sidecar. Exiting...", e.InnerException?.Message ?? e.Message);
|
|
// _lifetime.StopApplication();
|
|
// }
|
|
|
|
// _logger.LogInformation($"The customers are ready to place their orders!");
|
|
|
|
stoppingToken.Register(() =>
|
|
{
|
|
_ordersTask.Wait();
|
|
_logger.LogInformation($"The remaining customers have cancelled their orders and are leaving the store.");
|
|
_lifetime.StopApplication();
|
|
});
|
|
|
|
int ordersCreated = 0;
|
|
do
|
|
{
|
|
try
|
|
{
|
|
_products = await _daprClient.InvokeMethodAsync<List<Product>>(HttpMethod.Get, OrderServiceDaprId, "product", stoppingToken);
|
|
}
|
|
catch(Exception e)
|
|
{
|
|
_logger.LogError("Error retrieving products. Retrying in 5 seconds. Message: {Message}", e.InnerException?.Message ?? e.Message);
|
|
await Task.Delay(5000, stoppingToken);
|
|
}
|
|
} while (!stoppingToken.IsCancellationRequested && _products == null);
|
|
|
|
do
|
|
{
|
|
await Task.Delay(_random.Next(minSecondsBetweenOrders, maxSecondsBetweenOrders + 1) * 1000, stoppingToken);
|
|
await CreateOrder(stoppingToken);
|
|
ordersCreated += 1;
|
|
|
|
} while (!stoppingToken.IsCancellationRequested && (ordersCreated < numOrders || numOrders == -1));
|
|
|
|
_logger.LogInformation($"The {(numOrders == 1 ? "customer has" : "customers have")} finished placing {numOrders} {(numOrders == 1 ? "order" : "orders")}.");
|
|
}
|
|
|
|
public async Task CreateOrder(CancellationToken stoppingToken)
|
|
{
|
|
CustomerOrder order = new CustomerOrder();
|
|
int custNum = _random.Next(0, customers.Length);
|
|
_logger.LogInformation("Customer {0} {1} with loyalty id {2} is placing an order.", customers[custNum].Item2, customers[custNum].Item3, customers[custNum].Item1);
|
|
order.StoreId = storeId;
|
|
order.FirstName = customers[custNum].Item2;
|
|
order.LastName = customers[custNum].Item3;
|
|
order.LoyaltyId = customers[custNum].Item1.ToString();
|
|
|
|
// Get total number of menu items (t) and ramdomly choose a number of them to order (n)
|
|
int numProducts = _products.Count;
|
|
int numOrderItems = _random.Next(1, Math.Min(numProducts, maxUniqueItemsPerOrder)); // Never order 0 items
|
|
|
|
// Randomly choose a number between (1-t), (n) times to get a random quantity of (n) items
|
|
List<CustomerOrderItem> orderItems = new List<CustomerOrderItem>();
|
|
List<int> productIndicies = new List<int>();
|
|
for (int i = 0; i < numOrderItems; i++)
|
|
{
|
|
int productIndex = _random.Next(1, numProducts + 1);
|
|
while (productIndicies.Contains(productIndex)) // Ensure no duplicate menu items within order
|
|
{
|
|
productIndex = _random.Next(1, numProducts + 1);
|
|
}
|
|
|
|
productIndicies.Add(productIndex);
|
|
var menuItem = _products.Find(x => x.ProductId == productIndex); // Assuming menuIds are numbered #1 to #menuItemTotal
|
|
int quantity = _random.Next(1, maxItemQuantity + 1);
|
|
|
|
orderItems.Add(new CustomerOrderItem
|
|
{
|
|
ProductId = productIndex,
|
|
Quantity = quantity
|
|
});
|
|
}
|
|
|
|
order.OrderItems = orderItems;
|
|
if (!stoppingToken.IsCancellationRequested)
|
|
{
|
|
var request = _daprClient.CreateInvokeMethodRequest<CustomerOrder>(OrderServiceDaprId, "order", order);
|
|
var response = await _daprClient.InvokeMethodWithResponseAsync(request);
|
|
|
|
if (!response.IsSuccessStatusCode)
|
|
{
|
|
_logger.LogInformation("Order was unsuccessful: {0} {1} {2}", (int)response.StatusCode, response.StatusCode, await response.Content.ReadAsStringAsync());
|
|
}
|
|
else
|
|
{
|
|
_ordersTask = Task.Delay(_random.Next(minSecondsToPlaceOrder, maxSecondsToPlaceOrder + 1) * 1000, stoppingToken); // Delay until next customer in the line id ready to order
|
|
await _ordersTask;
|
|
_logger.LogInformation("Customer {0} {1} has placed their order containing {2} items.", order.FirstName, order.LastName, order.OrderItems.Count);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |