-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathWorker.cs
156 lines (129 loc) · 6.43 KB
/
Worker.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Grpc.Core;
using Grpc.Net.Client;
using IdentityModel.Client;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ProductGrpc.Protos;
using ShoppingCartGrpc.Protos;
namespace ShoppingCartWorkerService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IConfiguration _config;
public Worker(ILogger<Worker> logger, IConfiguration config)
{
_logger = logger;
_config = config;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
//0 Get Token from IS4
//1 Create SC if not exist
//2 Retrieve products from product grpc with server stream
//3 Add sc items into SC with client stream
//0 Get Token from IS4
var token = await GetTokenFromIS4();
//1 Create SC if not exist
using var scChannel = GrpcChannel.ForAddress(_config.GetValue<string>("WorkerService:ShoppingCartServerUrl"));
var scClient = new ShoppingCartProtoService.ShoppingCartProtoServiceClient(scChannel);
var scModel = await GetOrCreateShoppingCartAsync(scClient, token);
// open sc client stream
using var scClientStream = scClient.AddItemIntoShoppingCart();
//2 Retrieve products from product grpc with server stream
using var productChannel = GrpcChannel.ForAddress(_config.GetValue<string>("WorkerService:ProductServerUrl"));
var productClient = new ProductProtoService.ProductProtoServiceClient(productChannel);
_logger.LogInformation("GetAllProducts started..");
using var clientData = productClient.GetAllProducts(new GetAllProductsRequest());
await foreach (var responseData in clientData.ResponseStream.ReadAllAsync())
{
_logger.LogInformation("GetAllProducts Stream Response: {responseData}", responseData);
//3 Add sc items into SC with client stream
var addNewScItem = new AddItemIntoShoppingCartRequest
{
Username = _config.GetValue<string>("WorkerService:UserName"),
DiscountCode = "CODE_100",
NewCartItem = new ShoppingCartItemModel
{
ProductId = responseData.ProductId,
Productname = responseData.Name,
Price = responseData.Price,
Color = "Black",
Quantity = 1
}
};
await scClientStream.RequestStream.WriteAsync(addNewScItem);
_logger.LogInformation("ShoppingCart Client Stream Added New Item : {addNewScItem}", addNewScItem);
}
await scClientStream.RequestStream.CompleteAsync();
var addItemIntoShoppingCartResponse = await scClientStream;
_logger.LogInformation("AddItemIntoShoppingCart Client Stream Response: {addItemIntoShoppingCartResponse}", addItemIntoShoppingCartResponse);
await Task.Delay(_config.GetValue<int>("WorkerService:TaskInterval"), stoppingToken);
}
}
private async Task<string> GetTokenFromIS4()
{
_logger.LogInformation("GetTokenFromIS4 Started..");
// discover endpoints from metadata
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(_config.GetValue<string>("WorkerService:IdentityServerUrl"));
if (disco.IsError)
{
_logger.LogError(disco.Error);
return string.Empty;
}
_logger.LogInformation("Discovery endpoint taken from IS4 metadata. Discovery : {disco}", disco.TokenEndpoint);
// request token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "ShoppingCartClient",
ClientSecret = "secret",
Scope = "ShoppingCartAPI"
});
if (tokenResponse.IsError)
{
_logger.LogError(tokenResponse.Error);
return string.Empty;
}
_logger.LogInformation("Token retrieved for IS4. Token : {token}", tokenResponse.AccessToken);
return tokenResponse.AccessToken;
}
private async Task<ShoppingCartModel> GetOrCreateShoppingCartAsync(ShoppingCartProtoService.ShoppingCartProtoServiceClient scClient, string token)
{
ShoppingCartModel shoppingCartModel;
try
{
_logger.LogInformation("GetShoppingCartAsync started..");
var headers = new Metadata();
headers.Add("Authorization", $"Bearer {token}");
shoppingCartModel = await scClient.GetShoppingCartAsync(new GetShoppingCartRequest { Username = _config.GetValue<string>("WorkerService:UserName") }, headers);
_logger.LogInformation("GetShoppingCartAsync Response: {shoppingCartModel}", shoppingCartModel);
}
catch (RpcException exception)
{
if (exception.StatusCode == StatusCode.NotFound)
{
_logger.LogInformation("CreateShoppingCartAsync started..");
shoppingCartModel = await scClient.CreateShoppingCartAsync(new ShoppingCartModel { Username = _config.GetValue<string>("WorkerService:UserName") });
_logger.LogInformation("CreateShoppingCartAsync Response: {shoppingCartModel}", shoppingCartModel);
}
else
{
throw exception;
}
}
return shoppingCartModel;
}
}
}