Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 0 additions & 47 deletions .github/workflows/prlinked.yml

This file was deleted.

62 changes: 33 additions & 29 deletions TransactionProcessing.MerchantPos/Runtime/MerchantRuntime.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
using MerchantPos.EF.Persistence;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using SecurityService.DataTransferObjects.Responses;
using SimpleResults;
using System.Threading;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
using SecurityService.Client;
using SecurityService.DataTransferObjects.Responses;
using Shared.Logger;
using Shared.Results;
using SimpleResults;
using System.Threading;
using MerchantPos.EF.Models;
using TransactionProcessing.MerchantPos.Runtime;

public class MerchantRuntime
Expand Down Expand Up @@ -38,9 +40,9 @@ public async Task RunAsync((String clientId, String clientSecret) serviceClient,
{
try
{
// Get the service client token here ( can manage the expiry/caching at this level)
Result<TokenResponse> serviceToken = await this.GetToken(this.CurrentServiceToken, serviceClient, cancellationToken);
this.CurrentServiceToken = serviceToken.Data;
// Get the service client token here (can manage the expiry/caching at this level)
//Result<TokenResponse> serviceToken = await this.GetToken(this.CurrentServiceToken, serviceClient, cancellationToken);
//this.CurrentServiceToken = serviceToken.Data;

await StartupSequence(posClient.clientId, posClient.clientSecret, config, cancellationToken);
await RunMainLoop(posClient.clientId, posClient.clientSecret, config, cancellationToken);
Expand All @@ -53,47 +55,49 @@ public async Task RunAsync((String clientId, String clientSecret) serviceClient,
}
}

private async Task<Result<TokenResponse>> GetToken(TokenResponse currentToken, (String clientId, String clientSecret) serviceClient,
private async Task<Result> GetToken((String clientId, String clientSecret) serviceClient,
CancellationToken cancellationToken)
{
if (currentToken == null)
if (this.CurrentServiceToken == null)
{
Result<TokenResponse> tokenResult = await this.SecurityServiceClient.GetToken(serviceClient.clientId, serviceClient.clientSecret, cancellationToken);
if (tokenResult.IsFailed)
return ResultHelpers.CreateFailure(tokenResult);
TokenResponse token = tokenResult.Data;
Logger.LogDebug($"Token is {token.AccessToken}");
return Result.Success(token);
this.CurrentServiceToken = token;
return Result.Success();
}

if (currentToken.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2))
if (this.CurrentServiceToken.Expires.UtcDateTime.Subtract(DateTime.UtcNow) < TimeSpan.FromMinutes(2))
{
Logger.LogDebug($"Token is about to expire at {currentToken.Expires.DateTime:O}");
Logger.LogDebug($"Token is about to expire at {this.CurrentServiceToken.Expires.DateTime:O}");
Result<TokenResponse> tokenResult = await this.SecurityServiceClient.GetToken(serviceClient.clientId, serviceClient.clientSecret, cancellationToken);
if (tokenResult.IsFailed)
return ResultHelpers.CreateFailure(tokenResult);
TokenResponse token = tokenResult.Data;
Logger.LogDebug($"Token is {token.AccessToken}");
return Result.Success(token);
this.CurrentServiceToken = token;
return Result.Success();
}

return Result.Success(currentToken);
return Result.Success();
}

private async Task StartupSequence(String clientId,
String clientSecret,
MerchantConfig cfg,
CancellationToken cancellationToken) {
// 1. Token
Result<TokenResponse> tokenResult = await this.ApiClient.GetToken(clientId, clientSecret, cfg, cancellationToken);
Result tokenResult = await this.GetToken((clientId, clientSecret), cancellationToken);

if (tokenResult.IsFailed) {
Logger.LogWarning($"Failed to get token for merchant {cfg.MerchantName} during startup sequence.");
return;
}

// 2. Load products
var products = await ApiClient.GetProductList(cfg, tokenResult.Data, cancellationToken);
List<Product> products = await ApiClient.GetProductList(cfg, this.CurrentServiceToken, cancellationToken);
cfg.Products = products;

// 3. Balance
Expand All @@ -108,11 +112,11 @@ private async Task RunMainLoop(String clientId,
TimeSpan saleInterval = TimeSpan.FromSeconds(cfg.SaleIntervalSeconds);

while (!token.IsCancellationRequested) {
var merchant = await this.Repository.GetMerchant(cfg.MerchantId);
Merchant merchant = await this.Repository.GetMerchant(cfg.MerchantId);
// Wait until the merchant's configured opening time
var currentTime = DateTime.Now;
var openingTime = cfg.OpeningTime.ToTimeSpan();
var closingTime = cfg.ClosingTime.ToTimeSpan();
DateTime currentTime = DateTime.Now;
TimeSpan openingTime = cfg.OpeningTime.ToTimeSpan();
TimeSpan closingTime = cfg.ClosingTime.ToTimeSpan();
if (currentTime.TimeOfDay < openingTime) {
TimeSpan delay = openingTime - currentTime.TimeOfDay;
Logger.LogInformation($"Merchant {cfg.MerchantName} sleeping until opening time {cfg.OpeningTime}");
Expand Down Expand Up @@ -142,17 +146,17 @@ private async Task RunMainLoop(String clientId,
continue;
}

var now = DateTime.Now;
DateTime now = DateTime.Now;
if (merchant.LastLogonDateTime.Date != now.Date)
{
var tokenResult = await this.ApiClient.GetToken(clientId, clientSecret, cfg, token);
Result tokenResult = await this.GetToken((clientId, clientSecret), token);
if (tokenResult.IsFailed)
{
Logger.LogWarning($"Failed to obtain token for daily logon for merchant {cfg.MerchantName}");
}
else
{
await ApiClient.SendLogon(cfg, tokenResult.Data, merchant.TransactionNumber, token);
await ApiClient.SendLogon(cfg, this.CurrentServiceToken, merchant.TransactionNumber, token);
//_lastDailyLogonDate = now.Date;
await this.Repository.UpdateLastLogon(cfg.MerchantId, cfg.MerchantName, now);
Logger.LogInformation($"Performed daily logon for merchant {cfg.MerchantName} on {now:yyyy-MM-dd}");
Expand All @@ -170,7 +174,7 @@ private async Task RunMainLoop(String clientId,

private async Task DoSaleCycle(String clientId, String clientSecret, MerchantConfig cfg,Int32 transactionNumber, CancellationToken cancellationToken)
{
Result<TokenResponse> tokenResult = await this.ApiClient.GetToken(clientId, clientSecret, cfg, cancellationToken);
Result tokenResult = await this.GetToken((clientId, clientSecret), cancellationToken);
if (tokenResult.IsFailed)
return;

Expand All @@ -189,7 +193,7 @@ private async Task DoSaleCycle(String clientId, String clientSecret, MerchantCon
bool induceFail = _rng.NextDouble() < cfg.FailureInjectionProbability;
decimal saleValue = induceFail ? balance + 10 : value;

SaleResponse result = await ApiClient.SendSale(cfg, tokenResult.Data, product, saleValue, transactionNumber, cancellationToken);
SaleResponse result = await ApiClient.SendSale(cfg, this.CurrentServiceToken, product, saleValue, transactionNumber, cancellationToken);

if (result.Authorised)
{
Expand All @@ -215,12 +219,12 @@ private async Task DoSaleCycle(String clientId, String clientSecret, MerchantCon

private async Task DoReconciliation(String clientId, String clientSecret, MerchantConfig cfg, CancellationToken cancellationToken)
{
var tokenResult = await this.ApiClient.GetToken(clientId, clientSecret, cfg, cancellationToken);
Result tokenResult = await this.GetToken((clientId, clientSecret), cancellationToken);
if (tokenResult.IsFailed)
return;

var totals = await Repository.GetTotals(cfg.MerchantId);
await ApiClient.SendReconciliation(cfg, tokenResult.Data, totals, cancellationToken);
List<OperatorTotal> totals = await Repository.GetTotals(cfg.MerchantId);
await ApiClient.SendReconciliation(cfg, this.CurrentServiceToken, totals, cancellationToken);

// Clear totals
await this.Repository.UpdateLastEndOfDay(cfg.MerchantId, cfg.MerchantName, DateTime.Now);
Expand Down
Loading