diff --git a/TransactionProcessing.SchedulerService/JobTestDriver/Program.cs b/TransactionProcessing.SchedulerService/JobTestDriver/Program.cs index f958909..55ad597 100644 --- a/TransactionProcessing.SchedulerService/JobTestDriver/Program.cs +++ b/TransactionProcessing.SchedulerService/JobTestDriver/Program.cs @@ -1,4 +1,8 @@ -namespace JobTestDriver +using Quartz; +using Quartz.Core; +using Quartz.Impl; + +namespace JobTestDriver { using EstateManagement.Client; using MessagingService.Client; @@ -10,6 +14,7 @@ internal class Program{ static async Task Main(string[] args){ + //List<(String groupName, String streamName, Int64 parkedMessageCount)>? info = await Jobs.GetParkedQueueInformation("esdb://admin:changeit@192.168.0.133:2113?tls=false&tlsVerifyCert=false", CancellationToken.None); //foreach ((String groupName, String streamName, Int64 parkedMessageCount) infoItem in info){ // Console.WriteLine($"Group: {infoItem.groupName} Stream: {infoItem.streamName} Parked Count: {infoItem.parkedMessageCount}"); @@ -32,39 +37,39 @@ static async Task Main(string[] args){ // messagingServiceClient, // CancellationToken.None); - HttpClientHandler handler = new HttpClientHandler - { - ServerCertificateCustomValidationCallback = (message, - cert, - chain, - errors) => { - return true; - } - }; - HttpClient client = new HttpClient(handler); - ISecurityServiceClient securityServiceClient = new SecurityServiceClient(delegate(String s){ return "https://192.168.1.167:5001"; },client); IEstateClient estateClient = new EstateClient(delegate (String s) { return "http://192.168.1.167:5000"; }, client); - ITransactionProcessorClient transactionProcessorClient = new TransactionProcessorClient(delegate (String s) { return "https://eojrtqfzvyheu0l.m.pipedream.net"; }, client); - String estateManagementApi = "http://192.168.1.167:5000"; - String fileProcessorApi = "http://192.168.1.167:5009"; - String testHostApi = "http://192.168.1.167:9000"; - String clientId = "serviceClient"; - String clientSecret = "d192cbc46d834d0da90e8a9d50ded543"; + //HttpClientHandler handler = new HttpClientHandler + // { + // ServerCertificateCustomValidationCallback = (message, + // cert, + // chain, + // errors) => { + // return true; + // } + // }; + //HttpClient client = new HttpClient(handler); + //ISecurityServiceClient securityServiceClient = new SecurityServiceClient(delegate(String s){ return "https://192.168.1.167:5001"; },client); IEstateClient estateClient = new EstateClient(delegate (String s) { return "http://192.168.1.167:5000"; }, client); + //ITransactionProcessorClient transactionProcessorClient = new TransactionProcessorClient(delegate (String s) { return "https://eojrtqfzvyheu0l.m.pipedream.net"; }, client); + //String estateManagementApi = "http://192.168.1.167:5000"; + //String fileProcessorApi = "http://192.168.1.167:5009"; + //String testHostApi = "http://192.168.1.167:9000"; + //String clientId = "serviceClient"; + //String clientSecret = "d192cbc46d834d0da90e8a9d50ded543"; - ITransactionDataGenerator t = new TransactionDataGenerator(securityServiceClient, - estateClient, - transactionProcessorClient, - estateManagementApi, - fileProcessorApi, - testHostApi, - clientId, - clientSecret, - RunningMode.Live); - Guid estateId = Guid.Parse("435613ac-a468-47a3-ac4f-649d89764c22"); - Guid merchantId = Guid.Parse("ab1c99fb-1c6c-4694-9a32-b71be5d1da33"); - await Jobs.GenerateTransactions(t, estateId, merchantId, false, CancellationToken.None); - //var d = TransactionDataGenerator.GetTransactionDateTime(new Random(), DateTime.Now); - //Console.WriteLine(d); - await Jobs.PerformSettlement(t, DateTime.Now,estateId, CancellationToken.None); + //ITransactionDataGenerator t = new TransactionDataGenerator(securityServiceClient, + // estateClient, + // transactionProcessorClient, + // estateManagementApi, + // fileProcessorApi, + // testHostApi, + // clientId, + // clientSecret, + // RunningMode.Live); + //Guid estateId = Guid.Parse("435613ac-a468-47a3-ac4f-649d89764c22"); + //Guid merchantId = Guid.Parse("ab1c99fb-1c6c-4694-9a32-b71be5d1da33"); + //await Jobs.GenerateTransactions(t, estateId, merchantId, false, CancellationToken.None); + ////var d = TransactionDataGenerator.GetTransactionDateTime(new Random(), DateTime.Now); + ////Console.WriteLine(d); + //await Jobs.PerformSettlement(t, DateTime.Now,estateId, CancellationToken.None); } } } \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/BaseJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/BaseJob.cs index 9c66fdb..d36cc26 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/BaseJob.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/BaseJob.cs @@ -16,16 +16,7 @@ public abstract class BaseJob : IJob{ public String JobGroup{ get; private set; } - public String ClientSecret{ get; private set; } - - public String ClientId{ get; private set; } - - public String SecurityService { get; private set; } - - public String EstateManagementApi { get; private set; } - public String FileProcessorApi { get; private set; } - public String TransactionProcessorApi { get; private set; } - public String TestHostApi { get; private set; } + public BaseConfiguration BaseConfiguration; protected ITransactionDataGenerator CreateTransactionDataGenerator(String clientId, String clientSecret, RunningMode runningMode){ ISecurityServiceClient securityServiceClient = Bootstrapper.GetService(); @@ -72,7 +63,7 @@ public async Task Execute(IJobExecutionContext context){ this.CacheConfiguration(context); Logger.LogInformation($"Running Job Group: [{this.JobGroup}] Name: [{this.JobName}]"); - this.LogConfiguration(); + //this.LogConfiguration(); Bootstrapper.ConfigureServices(context); @@ -81,39 +72,20 @@ public async Task Execute(IJobExecutionContext context){ Logger.LogInformation($"Job Group: [{this.JobGroup}] Name: [{this.JobName}] completed"); } - private void LogConfiguration(){ - Logger.LogInformation($"Client Id: [{this.ClientId}]"); - Logger.LogInformation($"EstateManagementApi is: [{this.EstateManagementApi}]"); - Logger.LogInformation($"FileProcessorApi is: [{this.FileProcessorApi}]"); - Logger.LogInformation($"SecurityService is: [{this.SecurityService}]"); - Logger.LogInformation($"TestHostApi is: [{this.TestHostApi}]"); - Logger.LogInformation($"TransactionProcessorApi is: [{this.TransactionProcessorApi}]"); - } + //private void LogConfiguration(){ + // Logger.LogInformation($"Client Id: [{this.ClientId}]"); + // Logger.LogInformation($"EstateManagementApi is: [{this.EstateManagementApi}]"); + // Logger.LogInformation($"FileProcessorApi is: [{this.FileProcessorApi}]"); + // Logger.LogInformation($"SecurityService is: [{this.SecurityService}]"); + // Logger.LogInformation($"TestHostApi is: [{this.TestHostApi}]"); + // Logger.LogInformation($"TransactionProcessorApi is: [{this.TransactionProcessorApi}]"); + //} private void CacheConfiguration(IJobExecutionContext context){ this.JobName = context.JobDetail.Key.Name; this.JobGroup = context.JobDetail.Key.Group; - this.ClientId = context.MergedJobDataMap.GetString("ClientId"); - this.ClientSecret = context.MergedJobDataMap.GetString("ClientSecret"); - - if (context.MergedJobDataMap.ContainsKey("EstateManagementApi")){ - this.EstateManagementApi = context.MergedJobDataMap.GetString("EstateManagementApi"); - } - - if (context.MergedJobDataMap.ContainsKey("FileProcessorApi")){ - this.FileProcessorApi = context.MergedJobDataMap.GetString("FileProcessorApi"); - } - - if (context.MergedJobDataMap.ContainsKey("SecurityService")){ - this.SecurityService = context.MergedJobDataMap.GetString("SecurityService"); - } - - if (context.MergedJobDataMap.ContainsKey("TestHostApi")){ - this.TestHostApi = context.MergedJobDataMap.GetString("TestHostApi"); - } - - if (context.MergedJobDataMap.ContainsKey("TransactionProcessorApi")){ - this.TransactionProcessorApi = context.MergedJobDataMap.GetString("TransactionProcessorApi"); - } + + BaseConfiguration configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); + this.BaseConfiguration = configuration; } } \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateFileUploadsJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateFileUploadsJob.cs index 1a076d6..a20aa72 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateFileUploadsJob.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateFileUploadsJob.cs @@ -12,17 +12,11 @@ public class GenerateFileUploadsJob : BaseJob #region Methods public override async Task ExecuteJob(IJobExecutionContext context) { - Guid estateId = context.MergedJobDataMap.GetGuidValueFromString("EstateId"); - Guid merchantId = context.MergedJobDataMap.GetGuidValueFromString("MerchantId"); - Guid userId = context.MergedJobDataMap.GetGuidValueFromString("UserId"); + FileUploadJobConfig configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); - Logger.LogInformation($"Estate Id: [{estateId}]"); - Logger.LogInformation($"Merchant Id: [{merchantId}]"); - Logger.LogInformation($"User Id: [{userId}]"); - - ITransactionDataGenerator t = CreateTransactionDataGenerator(this.ClientId, this.ClientSecret, RunningMode.Live); + ITransactionDataGenerator t = CreateTransactionDataGenerator(configuration.ClientId, configuration.ClientSecret, RunningMode.Live); t.TraceGenerated += TraceGenerated; - await Jobs.GenerateFileUploads(t, estateId, merchantId, userId, context.CancellationToken); + await Jobs.GenerateFileUploads(t, configuration, context.CancellationToken); } #endregion } diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateMerchantStatementJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateMerchantStatementJob.cs index 96fe1b6..d12266d 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateMerchantStatementJob.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateMerchantStatementJob.cs @@ -10,12 +10,10 @@ public class GenerateMerchantStatementJob : BaseJob { public override async Task ExecuteJob(IJobExecutionContext context) { - Guid estateId = context.MergedJobDataMap.GetGuidValueFromString("EstateId"); + MerchantStatementJobConfig configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); - Logger.LogInformation($"Estate Id: [{estateId}]"); - - ITransactionDataGenerator t = this.CreateTransactionDataGenerator(this.ClientId, this.ClientSecret, RunningMode.Live); + ITransactionDataGenerator t = this.CreateTransactionDataGenerator(configuration.ClientId, configuration.ClientSecret, RunningMode.Live); t.TraceGenerated += TraceGenerated; - await Jobs.GenerateMerchantStatements(t, estateId, context.CancellationToken); + await Jobs.GenerateMerchantStatements(t, configuration, context.CancellationToken); } } \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateTransactionsJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateTransactionsJob.cs index cf77609..02fb5b5 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateTransactionsJob.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/GenerateTransactionsJob.cs @@ -1,10 +1,16 @@ -namespace TransactionProcessing.SchedulerService.Jobs +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace TransactionProcessing.SchedulerService.Jobs { using System; + using System.Text.Json.Nodes; + using System.Text.Json; using System.Threading.Tasks; using DataGeneration; using Quartz; using Shared.Logger; + using System.Linq; /// /// @@ -14,20 +20,116 @@ public class GenerateTransactionsJob : BaseJob{ #region Methods - public override async Task ExecuteJob(IJobExecutionContext context){ - - Guid estateId = context.MergedJobDataMap.GetGuidValueFromString("EstateId"); - Guid merchantId = context.MergedJobDataMap.GetGuidValueFromString("MerchantId"); - Boolean requireLogon = context.MergedJobDataMap.GetBooleanValueFromString("requireLogon"); + public override async Task ExecuteJob(IJobExecutionContext context) + { + TransactionJobConfig configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); - Logger.LogInformation($"Estate Id: [{estateId}]"); - Logger.LogInformation($"Merchant Id: [{merchantId}]"); - Logger.LogInformation($"Require Logon: [{requireLogon}]"); - - ITransactionDataGenerator t = CreateTransactionDataGenerator(this.ClientId, this.ClientSecret, RunningMode.Live); + ITransactionDataGenerator t = CreateTransactionDataGenerator(configuration.ClientId, configuration.ClientSecret, RunningMode.Live); t.TraceGenerated += TraceGenerated; - await Jobs.GenerateTransactions(t, estateId, merchantId, requireLogon, context.CancellationToken); + + await Jobs.GenerateTransactions(t, configuration, context.CancellationToken); } #endregion } + + public record BaseConfiguration( + String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi); + + public record MerchantStatementJobConfig(String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi,Guid EstateId) : BaseConfiguration(ClientId, ClientSecret, EstateManagementApi, FileProcessorApi, SecurityService, TestHostApi, TransactionProcessorApi); + + public record SettlementJobConfig(String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi, Guid EstateId) : BaseConfiguration(ClientId, ClientSecret, EstateManagementApi, FileProcessorApi, SecurityService, TestHostApi, TransactionProcessorApi); + + public record TransactionJobConfig(String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi, Guid EstateId, Guid MerchantId, Boolean IsLogon, List ContractNames) : BaseConfiguration(ClientId, ClientSecret, EstateManagementApi, FileProcessorApi, SecurityService, TestHostApi, TransactionProcessorApi); + + public record FileUploadJobConfig(String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi, Guid EstateId, Guid MerchantId, List ContractNames, Guid UserId) : BaseConfiguration(ClientId, ClientSecret, EstateManagementApi, FileProcessorApi, SecurityService, TestHostApi, TransactionProcessorApi); + + public record ReplayParkedQueueJobConfig(String ClientId, + String ClientSecret, + String EstateManagementApi, + String FileProcessorApi, + String SecurityService, + String TestHostApi, + String TransactionProcessorApi, String EventStoreAddress) : BaseConfiguration(ClientId, ClientSecret, EstateManagementApi, FileProcessorApi, SecurityService, TestHostApi, TransactionProcessorApi); + + public static class Helpers + { + public static T LoadJobConfig(JobDataMap jobDataMap) + { + String standardConfiguration = jobDataMap.GetString("Standard Configuration"); + String jobConfiguration = jobDataMap.GetString("Job Configuration"); + string fullConfig = Helpers.MergeJsonConfig(standardConfiguration, jobConfiguration); + T configuration = JsonConvert.DeserializeObject(fullConfig); + + return configuration; + } + + public static String MergeJsonConfig(String jsonDocument1, String jsonDocument2) + { + using (JsonDocument doc1 = JsonDocument.Parse(jsonDocument1)) + using (JsonDocument doc2 = JsonDocument.Parse(jsonDocument2)) + { + JsonObject mergedObject = new JsonObject(); + + foreach (var property in doc1.RootElement.EnumerateObject()) + { + mergedObject.Add(property.Name, property.Value.Clone()); + } + + foreach (var property in doc2.RootElement.EnumerateObject()) + { + if (mergedObject.ContainsKey(property.Name) && property.Value.ValueKind == JsonValueKind.Array) + { + JsonElement existingArray = mergedObject[property.Name]; + JsonElement newArray = property.Value; + + List mergedArray = existingArray.EnumerateArray().ToList(); + mergedArray.AddRange(newArray.EnumerateArray()); + + mergedObject[property.Name] = JsonDocument.Parse(JsonSerializer.Serialize(mergedArray)).RootElement; + } + else + { + mergedObject.Add(property.Name, property.Value.Clone()); + } + } + + string mergedJson = JsonSerializer.Serialize(mergedObject); + return mergedJson; + } + } + + internal class JsonObject : Dictionary + { + } + } } \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/Jobs.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/Jobs.cs index db78af2..a9a1949 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/Jobs.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/Jobs.cs @@ -21,11 +21,11 @@ using Shared.Logger; public static class Jobs{ - public static async Task GenerateMerchantStatements(ITransactionDataGenerator t, Guid estateId, CancellationToken cancellationToken){ - List merchants = await t.GetMerchants(estateId, cancellationToken); + public static async Task GenerateMerchantStatements(ITransactionDataGenerator t, MerchantStatementJobConfig config, CancellationToken cancellationToken){ + List merchants = await t.GetMerchants(config.EstateId, cancellationToken); if (merchants.Any() == false){ - throw new JobExecutionException($"No merchants returned for Estate [{estateId}]"); + throw new JobExecutionException($"No merchants returned for Estate [{config.EstateId}]"); } List results = new List(); @@ -42,13 +42,13 @@ public static async Task GenerateMerchantStatements(ITransactionDataGenerator t, } } - public static async Task GenerateFileUploads(ITransactionDataGenerator t, Guid estateId, Guid merchantId, Guid userId, CancellationToken cancellationToken) + public static async Task GenerateFileUploads(ITransactionDataGenerator t, FileUploadJobConfig config, CancellationToken cancellationToken) { - MerchantResponse merchant = await t.GetMerchant(estateId, merchantId, cancellationToken); + MerchantResponse merchant = await t.GetMerchant(config.EstateId, config.MerchantId, cancellationToken); if (merchant == default) { - throw new JobExecutionException($"No merchant returned for Estate Id [{estateId}] Merchant Id [{merchantId}]"); + throw new JobExecutionException($"No merchant returned for Estate Id [{config.EstateId}] Merchant Id [{config.MerchantId}]"); } List contracts = await t.GetMerchantContracts(merchant, cancellationToken); @@ -56,8 +56,11 @@ public static async Task GenerateFileUploads(ITransactionDataGenerator t, Guid e List results = new List(); foreach (ContractResponse contract in contracts) { + if (config.ContractNames.Contains(contract.Description) == false) + continue; + // Generate a file and upload - Boolean success = await t.SendUploadFile(fileDate, contract, merchant,userId, cancellationToken); + Boolean success = await t.SendUploadFile(fileDate, contract, merchant,config.UserId, cancellationToken); if (success == false) { @@ -71,12 +74,12 @@ public static async Task GenerateFileUploads(ITransactionDataGenerator t, Guid e } } - public static async Task GenerateTransactions(ITransactionDataGenerator t, Guid estateId, Guid merchantId, Boolean requireLogon, CancellationToken cancellationToken){ + public static async Task GenerateTransactions(ITransactionDataGenerator t, TransactionJobConfig config, CancellationToken cancellationToken){ // get the merchant - MerchantResponse merchant = await t.GetMerchant(estateId, merchantId, cancellationToken); + MerchantResponse merchant = await t.GetMerchant(config.EstateId, config.MerchantId, cancellationToken); if (merchant == default){ - throw new JobExecutionException($"Error getting Merchant Id [{merchantId}] for Estate Id [{estateId}]"); + throw new JobExecutionException($"Error getting Merchant Id [{config.MerchantId}] for Estate Id [{config.EstateId}]"); } DateTime transactionDate = DateTime.Now; @@ -89,7 +92,7 @@ public static async Task GenerateTransactions(ITransactionDataGenerator t, Guid throw new JobExecutionException($"No contracts returned for Merchant [{merchant.MerchantName}]"); } - if (requireLogon) + if (config.IsLogon) { // Do a logon transaction for the merchant Boolean logonSuccess = await t.PerformMerchantLogon(transactionDate, merchant, cancellationToken); @@ -98,11 +101,15 @@ public static async Task GenerateTransactions(ITransactionDataGenerator t, Guid { throw new JobExecutionException($"Error performing logon for Merchant [{merchant.MerchantName}]"); } + return; } + Random r = new Random(); List results = new List(); foreach (ContractResponse contract in contracts) { + if (config.ContractNames.Contains(contract.Description) == false) + continue; Int32 numberOfSales = r.Next(2, 4); // Generate and send some sales @@ -120,142 +127,29 @@ public static async Task GenerateTransactions(ITransactionDataGenerator t, Guid } } - public static async Task PerformSettlement(ITransactionDataGenerator t, DateTime dateTime, Guid estateId, CancellationToken cancellationToken) + public static async Task PerformSettlement(ITransactionDataGenerator t, DateTime dateTime, SettlementJobConfig config, CancellationToken cancellationToken) { - Boolean success = await t.PerformSettlement(dateTime.Date, estateId, cancellationToken); + Boolean success = await t.PerformSettlement(dateTime.Date, config.EstateId, cancellationToken); if (success == false){ - throw new JobExecutionException($"Error performing settlement for Estate Id [{estateId}] and date [{dateTime:dd-MM-yyyy}]"); + throw new JobExecutionException($"Error performing settlement for Estate Id [{config.EstateId}] and date [{dateTime:dd-MM-yyyy}]"); } } - - public static async Task> GetParkedQueueInformation(String eventStoreConnectionString, CancellationToken cancellationToken){ - EventStoreClientSettings clientSettings = EventStoreClientSettings.Create(eventStoreConnectionString); + + public static async Task ReplayParkedQueues(ReplayParkedQueueJobConfig config, CancellationToken cancellationToken) + { + EventStoreClientSettings clientSettings = EventStoreClientSettings.Create(config.EventStoreAddress); EventStore.Client.EventStorePersistentSubscriptionsClient client = new EventStorePersistentSubscriptionsClient(clientSettings); - List<(String groupName, String streamName, Int64 parkedMessageCount)> result = new List<(String groupName, String streamName, Int64 parkedMessageCount)>(); - IEnumerable x = await client.ListAllAsync(cancellationToken:cancellationToken); - foreach (PersistentSubscriptionInfo persistentSubscriptionInfo in x){ - if (persistentSubscriptionInfo.Stats.ParkedMessageCount > 0){ - // Add to replay list - result.Add((persistentSubscriptionInfo.GroupName, persistentSubscriptionInfo.EventSource, persistentSubscriptionInfo.Stats.ParkedMessageCount)); - } - } - return result; - } - - public static async Task> GetIncompleteFileList(String databaseConnectionString,CancellationToken cancellationToken){ - List<(Guid, String, DateTime, String)> result = new List<(Guid, String, DateTime, String)>(); - - using (SqlConnection connection = new SqlConnection(databaseConnectionString)){ - await connection.OpenAsync(cancellationToken); - - SqlCommand command = connection.CreateCommand(); - command.CommandText = "select FileId, FileLocation, FileReceivedDateTime, merchant.Name from [file] f inner join merchant on merchant.MerchantId = f.MerchantId where IsCompleted= 0"; - command.CommandType = CommandType.Text; - - var reader = await command.ExecuteReaderAsync(cancellationToken); - - while (await reader.ReadAsync(cancellationToken)){ - - var fileId = reader.GetGuid(0); - var fileLocation = reader.GetString(1); - var fileReceivedDateTime = reader.GetDateTime(2); - var merchantName = reader.GetString(3); - - result.Add((fileId, fileLocation, fileReceivedDateTime, merchantName)); - } - } - - return result; - } - - public static SendEmailRequest BuildSupportEmail(DateTime dateTime, - List<(Guid fileId, String fileLocation, DateTime fileReceivedDateTime, String merchantName)> incompleteFiles, - List<(String groupName, String streamName, Int64 parkedMessageCount)> parkedQueueInformation) - { - // Build uo the HTML String - StringBuilder htmlBuilder = new StringBuilder(); - - htmlBuilder.AppendLine(""); - htmlBuilder.AppendLine(""); - htmlBuilder.AppendLine(""); - htmlBuilder.AppendLine(""); - htmlBuilder.AppendLine(""); - - htmlBuilder.AppendLine(""); + IEnumerable subscriptions = await client.ListAllAsync(cancellationToken: cancellationToken); - htmlBuilder.AppendLine($"

Daily Support Report for {dateTime.ToString("dd-MM-yyyy")}

"); - - htmlBuilder.AppendLine("

Parked Messages Stats

"); - - if (parkedQueueInformation.Any() == false){ - htmlBuilder.AppendLine("

No Data

"); - } - else{ - htmlBuilder.AppendLine(""); - htmlBuilder.Append(""); - - foreach ((String groupName, String streamName, Int64 parkedMessageCount) info in parkedQueueInformation){ - htmlBuilder.Append($""); - } - - htmlBuilder.AppendLine("
GroupStreamParked Messages
{info.groupName}{info.streamName}{info.parkedMessageCount}
"); - } - - htmlBuilder.AppendLine("

Incomplete Bulk Files

"); - - if (incompleteFiles.Any() == false) - { - htmlBuilder.AppendLine("

No Data

"); - } - else + foreach (var persistentSubscriptionInfo in subscriptions) { - htmlBuilder.AppendLine(""); - htmlBuilder.Append(""); - - foreach ((Guid fileId, String fileLocation, DateTime fileReceivedDateTime, String merchantName) incompleteFile in incompleteFiles){ - - htmlBuilder.Append($""); + if (persistentSubscriptionInfo.Stats.ParkedMessageCount > 0) + { + await client.ReplayParkedMessagesToStreamAsync(persistentSubscriptionInfo.EventSource, + persistentSubscriptionInfo.GroupName, cancellationToken: cancellationToken); } - - htmlBuilder.AppendLine("
IdLocationFile ReceivedMerchant Name
{incompleteFile.fileId}{incompleteFile.fileLocation}{incompleteFile.fileReceivedDateTime}{incompleteFile.merchantName}
"); - } - - htmlBuilder.AppendLine(""); - htmlBuilder.AppendLine(""); - - SendEmailRequest request = new SendEmailRequest{ - Body = htmlBuilder.ToString(), - ConnectionIdentifier = Guid.NewGuid(), - FromAddress = "support@transactionprocessing.com", - IsHtml = true, - MessageId = Guid.NewGuid(), - Subject = $"Daily Support Report for {dateTime:dd-MM-yyyy}", - ToAddresses = new List{ - "stuart_ferguson1development@outlook.com" - } - }; - return request; - } - - public static async Task SendSupportEmail(DateTime dateTime, - String accessToken, - String eventStoreConnectionString, String databaseConnectionString, List estateIds, - IMessagingServiceClient messagingServiceClient, - CancellationToken cancellationToken) - { - List<(String groupName, String streamName, Int64 parkedMessageCount)> parkedQueueInfo = await Jobs.GetParkedQueueInformation(eventStoreConnectionString, cancellationToken); - List<(Guid, String, DateTime, String)> incompleteFiles = new List<(Guid, String, DateTime, String)>(); - foreach (String estateId in estateIds){ - String connectionString = databaseConnectionString.Replace("", estateId.ToString()); - incompleteFiles.AddRange(await GetIncompleteFileList(connectionString, cancellationToken)); } - - SendEmailRequest emailRequest = BuildSupportEmail(dateTime, incompleteFiles, parkedQueueInfo); - emailRequest.ConnectionIdentifier = Guid.Parse(estateIds.First()); - await messagingServiceClient.SendEmail(accessToken, emailRequest, CancellationToken.None); } } \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ProcessSettlementJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ProcessSettlementJob.cs index 4671bfb..d32143c 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ProcessSettlementJob.cs +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ProcessSettlementJob.cs @@ -11,13 +11,11 @@ public class ProcessSettlementJob : BaseJob { public override async Task ExecuteJob(IJobExecutionContext context) { - Guid estateId = context.MergedJobDataMap.GetGuidValueFromString("EstateId"); + SettlementJobConfig configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); - Logger.LogInformation($"Estate Id: [{estateId}]"); - - ITransactionDataGenerator t = CreateTransactionDataGenerator(this.ClientId, this.ClientSecret, RunningMode.Live); + ITransactionDataGenerator t = CreateTransactionDataGenerator(configuration.ClientId, configuration.ClientSecret, RunningMode.Live); t.TraceGenerated += TraceGenerated; - await Jobs.PerformSettlement(t, DateTime.Now, estateId, context.CancellationToken); + await Jobs.PerformSettlement(t, DateTime.Now, configuration, context.CancellationToken); } } } diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ReplayParkedQueuesJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ReplayParkedQueuesJob.cs new file mode 100644 index 0000000..d83fc57 --- /dev/null +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/ReplayParkedQueuesJob.cs @@ -0,0 +1,14 @@ +using System.Threading.Tasks; +using Quartz; + +namespace TransactionProcessing.SchedulerService.Jobs; + +public class ReplayParkedQueuesJob : BaseJob +{ + public override async Task ExecuteJob(IJobExecutionContext context) + { + ReplayParkedQueueJobConfig configuration = Helpers.LoadJobConfig(context.MergedJobDataMap); + + await Jobs.ReplayParkedQueues(configuration, context.CancellationToken); + } +} \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/SupportReportEmailJob.cs b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/SupportReportEmailJob.cs deleted file mode 100644 index 54ad9ad..0000000 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/SupportReportEmailJob.cs +++ /dev/null @@ -1,37 +0,0 @@ -namespace TransactionProcessing.SchedulerService.Jobs; - -using System; -using System.Linq; -using System.Threading.Tasks; -using MessagingService.Client; -using Quartz; -using Shared.Logger; - -public class SupportReportEmailJob : BaseJob -{ - #region Methods - public override async Task ExecuteJob(IJobExecutionContext context) - { - String eventStoreConnectionString = context.MergedJobDataMap.GetString("EventStoreConnectionString"); - String databaseConnectionString = context.MergedJobDataMap.GetString("DatabaseConnectionString"); - String estateIds = context.MergedJobDataMap.GetString("EstateIds"); - - Logger.LogInformation($"Estate Id: [{estateIds}]"); - - String token = await this.GetToken(this.ClientId, this.ClientSecret, context.CancellationToken); - - IMessagingServiceClient messagingServiceClient = Bootstrapper.GetService(); - - await Jobs.SendSupportEmail(DateTime.Now, - token, - eventStoreConnectionString, - databaseConnectionString, - estateIds.Split(',').ToList(), - messagingServiceClient, - context.CancellationToken); - } - - - - #endregion -} \ No newline at end of file diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/TransactionProcessing.SchedulerService.Jobs.csproj b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/TransactionProcessing.SchedulerService.Jobs.csproj index 4b1bd95..fa5c028 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/TransactionProcessing.SchedulerService.Jobs.csproj +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.Jobs/TransactionProcessing.SchedulerService.Jobs.csproj @@ -6,16 +6,16 @@ - + - - + + - - + + diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.csproj b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.csproj index d2d5de2..6e065f6 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.csproj +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService.csproj @@ -6,13 +6,13 @@ - - - - - + + + + + - + diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.development.json b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.development.json index 879deb7..6b8a386 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.development.json +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.development.json @@ -7,6 +7,6 @@ } }, "ConnectionStrings": { - "SchedulerReadModel": "server=127.0.0.1;user id=sa;password=Sc0tland;database=Scheduler;Encrypt=True;TrustServerCertificate=True" + "SchedulerReadModel": "server=127.0.0.1;user id=sa;password=sp1ttal;database=Scheduler;Encrypt=True;TrustServerCertificate=True" } } diff --git a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.json b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.json index 879deb7..6b8a386 100644 --- a/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.json +++ b/TransactionProcessing.SchedulerService/TransactionProcessing.SchedulerService/appsettings.json @@ -7,6 +7,6 @@ } }, "ConnectionStrings": { - "SchedulerReadModel": "server=127.0.0.1;user id=sa;password=Sc0tland;database=Scheduler;Encrypt=True;TrustServerCertificate=True" + "SchedulerReadModel": "server=127.0.0.1;user id=sa;password=sp1ttal;database=Scheduler;Encrypt=True;TrustServerCertificate=True" } }