-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathAppBase.cs
90 lines (79 loc) · 3.63 KB
/
AppBase.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
using Microsoft.EntityFrameworkCore;
using Samples.HelloCart.V2;
using static System.Console;
namespace Samples.HelloCart;
public abstract class AppBase
{
public IServiceProvider ServerServices { get; protected set; } = null!;
public IServiceProvider ClientServices { get; protected set; } = null!;
public virtual IServiceProvider WatchedServices => ClientServices;
public Product[] ExistingProducts { get; set; } = Array.Empty<Product>();
public Cart[] ExistingCarts { get; set; } = Array.Empty<Cart>();
public virtual async Task InitializeAsync(IServiceProvider services)
{
var dbContextFactory = services.GetService<IDbContextFactory<AppDbContext>>();
if (dbContextFactory != null) {
await using var dbContext = await dbContextFactory.CreateDbContextAsync();
await dbContext.Database.EnsureDeletedAsync();
await dbContext.Database.EnsureCreatedAsync();
}
var commander = services.Commander();
var pApple = new Product { Id = "apple", Price = 2M };
var pBanana = new Product { Id = "banana", Price = 0.5M };
var pCarrot = new Product { Id = "carrot", Price = 1M };
ExistingProducts = new [] { pApple, pBanana, pCarrot };
foreach (var product in ExistingProducts)
await commander.Call(new EditCommand<Product>(product));
var cart1 = new Cart() { Id = "cart:apple=1,banana=2",
Items = ImmutableDictionary<string, decimal>.Empty
.Add(pApple.Id, 1)
.Add(pBanana.Id, 2)
};
var cart2 = new Cart() { Id = "cart:banana=1,carrot=1",
Items = ImmutableDictionary<string, decimal>.Empty
.Add(pBanana.Id, 1)
.Add(pCarrot.Id, 1)
};
ExistingCarts = new [] { cart1, cart2 };
foreach (var cart in ExistingCarts)
await commander.Call(new EditCommand<Cart>(cart));
}
public virtual async ValueTask DisposeAsync()
{
if (ClientServices is IAsyncDisposable csd)
await csd.DisposeAsync();
if (ServerServices is IAsyncDisposable sd)
await sd.DisposeAsync();
}
public Task Watch(IServiceProvider services, CancellationToken cancellationToken = default)
{
var tasks = new List<Task>();
foreach (var product in ExistingProducts)
tasks.Add(WatchProduct(services, product.Id, cancellationToken));
foreach (var cart in ExistingCarts)
tasks.Add(WatchCartTotal(services, cart.Id, cancellationToken));
return Task.WhenAll(tasks);
}
public async Task WatchProduct(
IServiceProvider services, string productId, CancellationToken cancellationToken = default)
{
var productService = services.GetRequiredService<IProductService>();
var computed = await Computed.Capture(() => productService.Get(productId, cancellationToken));
while (true) {
WriteLine($" {computed.Value}");
await computed.WhenInvalidated(cancellationToken);
computed = await computed.Update(cancellationToken);
}
}
public async Task WatchCartTotal(
IServiceProvider services, string cartId, CancellationToken cancellationToken = default)
{
var cartService = services.GetRequiredService<ICartService>();
var computed = await Computed.Capture(() => cartService.GetTotal(cartId, cancellationToken));
while (true) {
WriteLine($" {cartId}: total = {computed.Value}");
await computed.WhenInvalidated(cancellationToken);
computed = await computed.Update(cancellationToken);
}
}
}