public async Task RunAsync(TimeSpan refreshInterval, CancellationToken cancellationToken = default(CancellationToken)) { try { var isPeriodStarted = true; //TODO read value from cache while (isPeriodStarted) { paymentLogger.LogInfo("Starting to refresh all Levy Accounts Details"); try { await accountBalanceService.RefreshLevyAccountDetails(cancellationToken); } catch (Exception e) { paymentLogger.LogError("Error While trying to refresh all Levy Accounts Details", e); } // isPeriodStarted = true //TODO read value from cache await Task.Delay(refreshInterval, cancellationToken); } } catch (TaskCanceledException e) { paymentLogger.LogError("Levy Accounts Refresh Task was Canceled", e); } catch (Exception e) { paymentLogger.LogError("Error While trying to refresh all Levy Accounts Details", e); throw; } }
public async Task RefreshLevyAccountDetails(CancellationToken cancellationToken = default(CancellationToken)) { logger.LogInfo("Now Trying to Refresh All Accounts Balance Details"); var page = 1; await retryPolicy.ExecuteAsync(GetTotalPageSize).ConfigureAwait(false); while (page <= totalPageSize) { cancellationToken.ThrowIfCancellationRequested(); try { var pagedAccountsRecords = await accountApiClient.GetPageOfAccounts(page, batchSize).ConfigureAwait(false); var pagedLevyAccountModels = MapToLevyAccountModel(pagedAccountsRecords); await BatchUpdateLevyAccounts(pagedLevyAccountModels, cancellationToken).ConfigureAwait(false); await PublishNotLevyPayerEmployerEvents(pagedLevyAccountModels).ConfigureAwait(false); logger.LogInfo($"Successfully retrieved Account Balance Details for Page {page} of Levy Accounts"); } catch (Exception e) { logger.LogError($"Error while retrieving Account Balance Details for Page {page} of Levy Accounts", e); } page++; } }
private async Task <List <(Object Message, BatchMessageReceiver Receiver, Message ReceivedMessage)> > ReceiveMessages(BatchMessageReceiver messageReceiver, CancellationToken cancellationToken) { var applicationMessages = new List <(Object Message, BatchMessageReceiver Receiver, Message ReceivedMessage)>(); var messages = await messageReceiver.ReceiveMessages(200, cancellationToken).ConfigureAwait(false); if (!messages.Any()) { return(applicationMessages); } foreach (var message in messages) { cancellationToken.ThrowIfCancellationRequested(); try { var applicationMessage = GetApplicationMessage(message); applicationMessages.Add((applicationMessage, messageReceiver, message)); } catch (Exception e) { logger.LogError($"Error deserialising the message. Error: {e.Message}", e); //TODO: should use the error queue instead of dead letter queue await messageReceiver.DeadLetter(message) .ConfigureAwait(false); } } return(applicationMessages); }
public async Task RefreshLevyAccountDetails(int pageNumber, CancellationToken cancellationToken = default(CancellationToken)) { logger.LogInfo("Now Trying to Refresh All Accounts Balance Details"); cancellationToken.ThrowIfCancellationRequested(); try { var pagedAccountsRecords = await accountApiClient.GetPageOfAccounts(pageNumber, batchSize).ConfigureAwait(false); var pagedLevyAccountModels = MapToLevyAccountModel(pagedAccountsRecords); var storedEmployers = await levyFundingSourceRepository.GetCurrentEmployerStatus(pagedLevyAccountModels.Select(x => x.AccountId).ToList(), cancellationToken); await BatchUpdateLevyAccounts(pagedLevyAccountModels, cancellationToken).ConfigureAwait(false); await PublishEmployerEvents(pagedLevyAccountModels, storedEmployers).ConfigureAwait(false); logger.LogInfo($"Successfully retrieved Account Balance Details for Page {pageNumber} of Levy Accounts"); } catch (Exception e) { logger.LogError($"Error while retrieving Account Balance Details for Page {pageNumber} of Levy Accounts", e); } }
public async Task HandleEmployerProviderPriorityChange(EmployerChangedProviderPriority message) { try { using (var operation = telemetry.StartOperation("LevyFundedService.HandleEmployerProviderPriorityChange", message.EventId.ToString())) { var stopwatch = Stopwatch.StartNew(); paymentLogger.LogDebug( $"Storing EmployerChangedProviderPriority event for {Id}, Account Id: {message.EmployerAccountId}"); await employerProviderPriorityStorageService.StoreEmployerProviderPriority(message) .ConfigureAwait(false); paymentLogger.LogInfo( $"Finished Storing EmployerChangedProviderPriority event for {Id}, Account Id: {message.EmployerAccountId}"); TrackInfrastructureEvent("LevyFundedService.HandleEmployerProviderPriorityChange", stopwatch); telemetry.StopOperation(operation); } } catch (Exception ex) { paymentLogger.LogError( $"Error while handling EmployerChangedProviderPriority event for {Id}, Account Id: {message.EmployerAccountId} Error:{ex.Message}", ex); throw; } }
public async Task RefreshLevyAccountDetails(int pageNumber, CancellationToken cancellationToken = default(CancellationToken)) { try { paymentLogger.LogInfo($"Starting to refresh page of Levy Accounts Details (Page {pageNumber})"); try { await accountBalanceService.RefreshLevyAccountDetails(pageNumber, cancellationToken); } catch (Exception e) { paymentLogger.LogError($"Error While trying to refresh page of Levy Accounts Details (Page {pageNumber})", e); } } catch (TaskCanceledException e) { paymentLogger.LogError($"Levy Accounts Refresh Task was Canceled (Page {pageNumber})", e); } catch (Exception e) { paymentLogger.LogError($"Error While trying to refresh page of Levy Accounts Details (Page {pageNumber})", e); throw; } }
public async Task RunAsync(CancellationToken cancellationToken) { try { logger.LogInfo($"PaymentsEventModelBatchService for {typeof(T).Name} started"); while (true) { cancellationToken.ThrowIfCancellationRequested(); try { await policy.ExecuteAsync(() => StorePayments(cancellationToken)); } catch (Exception ex) { logger.LogError($"Error while storing batch. Error: {ex.Message}", ex); } await Task.Delay(batchInterval, cancellationToken); } } catch (TaskCanceledException) { logger.LogInfo($"Cancellation requested, stopping PaymentsEventModelBatchService for {typeof(T).Name}"); } catch (Exception ex) { logger.LogFatal($"Fatal error while storing batch. Error: {ex.Message}", ex); } }
protected override async Task RunAsync(CancellationToken cancellationToken) { var initialised = false; try { logger.LogDebug("Starting the Earning Events service."); jobContextManager = lifetimeScope.Resolve <IJobContextManager <JobContextMessage> >(); jobContextManager.OpenAsync(cancellationToken); initialised = true; logger.LogInfo("Started the Earning Events service."); await Task.Delay(Timeout.Infinite, cancellationToken); } catch (Exception exception) when(!(exception is TaskCanceledException)) { // Ignore, as an exception is only really thrown on cancellation of the token. logger.LogError($"Reference Data Stateless Service Exception. Error: {exception}.", exception); } finally { if (initialised) { logger.LogInfo("Earning Events Stateless Service End"); await jobContextManager.CloseAsync(); } } }
public async Task <ReadOnlyCollection <PeriodisedRequiredPaymentEvent> > HandlePayableEarningEvent(PayableEarningEvent earningEvent, CancellationToken cancellationToken) { paymentLogger.LogVerbose($"Handling PayableEarningEvent for jobId:{earningEvent.JobId} with apprenticeship key based on {logSafeApprenticeshipKeyString}"); try { using (var operation = telemetry.StartOperation("RequiredPaymentsService.HandlePayableEarningEvent", earningEvent.EventId.ToString())) { var stopwatch = Stopwatch.StartNew(); await ResetPaymentHistoryCacheIfDifferentCollectionPeriod(earningEvent.CollectionPeriod) .ConfigureAwait(false); await Initialise(earningEvent.CollectionPeriod.Period).ConfigureAwait(false); var requiredPaymentEvents = await payableEarningEventProcessor.HandleEarningEvent(earningEvent, paymentHistoryCache, cancellationToken).ConfigureAwait(false); Log(requiredPaymentEvents); telemetry.TrackDuration("RequiredPaymentsService.HandlePayableEarningEvent", stopwatch, earningEvent); telemetry.StopOperation(operation); return(requiredPaymentEvents); } } catch (Exception e) { paymentLogger.LogError($"Error handling payable earning. Error: {e.Message}"); throw; } }
private async Task <List <LevyAccountModel> > GetPaymentsLevyAccountDetails() { paymentLogger.LogDebug("Started Importing Payments Employer Accounts"); List <LevyAccountModel> levyAccountModels; try { levyAccountModels = await paymentsDataContext.LevyAccount.ToListAsync(); if (levyAccountModels.IsNullOrEmpty()) { return(null); } } catch (Exception e) { paymentLogger.LogError("Error while retrieving Account Balance Details from PaymentsV2", e); return(null); } paymentLogger.LogInfo("Finished Importing Payments Employer Accounts"); return(levyAccountModels); }
public async Task <int> Process(int batchSize, CancellationToken cancellationToken) { logger.LogVerbose("Processing batch."); var batch = await cache.GetPayments(batchSize, cancellationToken).ConfigureAwait(false); if (batch.Count < 1) { logger.LogVerbose("No records found to process."); return(0); } using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { try { foreach (var item in batch) { logger.LogVerbose($"Saving {typeof(T).Name} to table: {item.ToString()}"); await bulkWriter.Write(item, cancellationToken).ConfigureAwait(false); } await bulkWriter.Flush(cancellationToken).ConfigureAwait(false); scope.Complete(); } catch (Exception e) { logger.LogError($"Error performing bulk copy for model type: {typeof(T).Name}. Error: {e.Message}", e); throw; } } return(batch.Count); }
private async Task <List <LevyAccountModel> > GetPageOfLevyAccounts(int pageNumber, CancellationToken cancellationToken = default(CancellationToken)) { cancellationToken.ThrowIfCancellationRequested(); try { var pagedAccountsRecords = await accountApiClient.GetPageOfAccounts(pageNumber, accountApiBatchSize).ConfigureAwait(false); return(MapToLevyAccountModel(pagedAccountsRecords)); } catch (Exception e) { logger.LogError($"Error while retrieving Account Balance Details for Page {pageNumber} of Levy Accounts", e); return(new List <LevyAccountModel>()); } }
public async Task RunAsync(CancellationToken cancellationToken) { var initialised = false; try { logger.LogDebug("Starting the Job Context Manager service."); jobContextManager.OpenAsync(cancellationToken); initialised = true; logger.LogInfo("Started the Job Context Manager service."); await Task.Delay(Timeout.Infinite, cancellationToken); } catch (Exception exception) when(!(exception is TaskCanceledException)) { logger.LogError($"Error running DC job context manager. Error: {exception.Message}.", exception); throw; } finally { if (initialised) { logger.LogDebug("Closing the job context manager."); await jobContextManager.CloseAsync(); logger.LogInfo("Closed job context manager."); } } }
public async Task Handle(CalculatedRequiredCoInvestedAmount message, IMessageHandlerContext context) { paymentLogger.LogInfo($"Processing Required Payment Service event for Message Id : {context.MessageId}"); var currentExecutionContext = (ESFA.DC.Logging.ExecutionContext)executionContext; currentExecutionContext.JobId = message.JobId.ToString(); var payments = contractType2RequiredPaymentService.GetFundedPayments(message); foreach (var recordablePaymentEvent in payments) { try { await context.Publish(recordablePaymentEvent); paymentLogger.LogInfo($"Successfully published CoInvestedPayment of Type {recordablePaymentEvent.GetType().Name}"); } catch (Exception ex) { paymentLogger.LogError($"Error publishing the event: RecordablePaymentEvent", ex); throw; } } paymentLogger.LogInfo($"Successfully processed NonLevyFunded Service event for Job Id {message.JobId}"); }
public async Task <int> Process(int batchSize, CancellationToken cancellationToken) { logger.LogVerbose("Processing batch."); var batch = await cache.GetPayments(batchSize, cancellationToken).ConfigureAwait(false); if (batch.Count < 1) { logger.LogVerbose("No records found to process."); return(0); } try { using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew, TransactionScopeAsyncFlowOption.Enabled)) { foreach (var changeEvent in batch) { await SaveDataLockEvent(cancellationToken, changeEvent); foreach (var period in changeEvent.Periods) { await SaveEventPeriods(period, changeEvent, cancellationToken); } foreach (var commitment in changeEvent.CommitmentVersions) { await SaveCommitmentVersion(commitment, changeEvent, cancellationToken); } foreach (var error in changeEvent.Errors) { await SaveErrorCode(error, changeEvent, cancellationToken); } logger.LogDebug( $"Saved PriceEpisodeStatusChange event {changeEvent.DataLock.DataLockEventId} for UKPRN {changeEvent.DataLock.UKPRN}. " + $"Commitment versions: {changeEvent.CommitmentVersions.Length}, " + $"periods: {changeEvent.Periods.Length}, errors: {changeEvent.Errors.Length}"); } await dataLockEventWriter.Flush(cancellationToken); await dataLockEventCommitmentVersionWriter.Flush(cancellationToken); await dataLockEventPeriodWriter.Flush(cancellationToken); await dataLockEventErrorWriter.Flush(cancellationToken); scope.Complete(); } } catch (Exception e) { logger.LogError($"Error saving batch of DataLockStatusChanged events. Error: {e.Message}", e); throw; } return(batch.Count); }
public async Task Process(ApprenticeshipCreatedEvent createdEvent) { try { logger.LogDebug($"Now processing the apprenticeship created event. " + $"Apprenticeship id: {createdEvent.ApprenticeshipId}, " + $"employer account id: {createdEvent.AccountId}, " + $"Ukprn: {createdEvent.ProviderId}."); var model = mapper.Map <ApprenticeshipModel>(createdEvent); var duplicates = await apprenticeshipService.NewApprenticeship(model).ConfigureAwait(false); logger.LogDebug($"Apprenticeship saved to database. " + $"Apprenticeship id: {createdEvent.ApprenticeshipId}, " + $"employer account id: {createdEvent.AccountId}, " + $"Ukprn: {createdEvent.ProviderId}."); var updatedEvent = mapper.Map <ApprenticeshipUpdated>(model); updatedEvent.Duplicates = duplicates.Select(duplicate => new ApprenticeshipDuplicate { Ukprn = duplicate.Ukprn, ApprenticeshipId = duplicate.ApprenticeshipId }).ToList(); var endpointInstance = await endpointInstanceFactory.GetEndpointInstance().ConfigureAwait(false); await endpointInstance.Publish(updatedEvent).ConfigureAwait(false); logger.LogInfo($"Finished processing the apprenticeship created event. " + $"Apprenticeship id: {createdEvent.ApprenticeshipId}, " + $"employer account id: {createdEvent.AccountId}, " + $"Ukprn: {createdEvent.ProviderId}."); } catch (ApprenticeshipAlreadyExistsException e) { logger.LogWarning($"Apprenticeship already exists while trying to add a new apprenticeship: {e.Message}\n" + $"Apprenticeship id: {createdEvent.ApprenticeshipId}, " + $"employer account id: {createdEvent.AccountId}, " + $"Ukprn: {createdEvent.ProviderId}."); } catch (InvalidOperationException e) { logger.LogError($"Unhandled exception while adding apprenticeship: {e.Message}\n" + $"Apprenticeship id: {createdEvent.ApprenticeshipId}, " + $"employer account id: {createdEvent.AccountId}, " + $"Ukprn: {createdEvent.ProviderId}.", e); throw; } catch (Exception ex) { logger.LogError($"Error processing the apprenticeship event. Error: {ex.Message}", ex); throw; } }
private async Task LoadExistingJobs() { try { using (var scope = scopeFactory.Create("LoadExistingJobs")) { var jobStorage = scope.Resolve <IJobStorageService>(); var jobs = await jobStorage.GetCurrentJobs(cancellationToken).ConfigureAwait(false); foreach (var job in jobs) { StartMonitoringJob(job, JobType.EarningsJob); } } } catch (Exception e) { logger.LogError("Failed to load existing jobs."); } }
private async Task LoadExistingJobs() { try { using (var scope = scopeFactory.Create("LoadExistingJobs")) { var jobStorage = scope.Resolve <IJobStorageService>(); var jobs = await GetCurrentJobs(jobStorage); foreach (var job in jobs) { StartMonitoringJob(job, JobType.EarningsJob); } } } catch (Exception e) { logger.LogError($"Failed to load existing jobs. Error: {e.Message}", e); } }
private static async Task RunApprenticeshipsReferenceDataComparison(IApprenticeshipsDataService service, IPaymentLogger log) { try { await service.ProcessComparison(); } catch (Exception e) { log.LogError("Error in ProcessComparison", e); throw; } }
public PeriodisedRequiredPaymentEvent Create(EarningType earningType, int transactionType) { PeriodisedRequiredPaymentEvent paymentEvent = null; switch (earningType) { case EarningType.CoInvested: if (IsValidPaymentType <OnProgrammeEarningType>(transactionType)) { paymentEvent = new CalculatedRequiredCoInvestedAmount { OnProgrammeEarningType = (OnProgrammeEarningType)transactionType, }; } break; case EarningType.Incentive: if (IsValidPaymentType <IncentivePaymentType>(transactionType)) { paymentEvent = new CalculatedRequiredIncentiveAmount { Type = (IncentivePaymentType)transactionType, }; } break; case EarningType.Levy: if (IsValidPaymentType <OnProgrammeEarningType>(transactionType)) { paymentEvent = new CalculatedRequiredLevyAmount { OnProgrammeEarningType = (OnProgrammeEarningType)transactionType, }; } break; default: throw new InvalidOperationException( $"Unknown earning type found: {earningType:G}. Cannot create the PeriodisedRequiredPaymentEvent."); } if (paymentEvent == null) { logger.LogError( $"Invalid EarningType and TransactionType combination: EarningType: {earningType:G}, TransactionType: {transactionType}"); } return(paymentEvent); }
protected override async Task RunAsync(CancellationToken cancellationToken) { try { logger.LogDebug("Starting the DC JobContextMessageService for the Period End service."); jobContextManagerService = lifetimeScope.Resolve <IJobContextManagerService>(); await jobContextManagerService.RunAsync(cancellationToken); } catch (Exception ex) when(!(ex is TaskCanceledException)) { logger.LogError($"Error starting the job context manager. Error: {ex.Message}", ex); throw; } }
public async Task <List <ProviderAdjustment> > GetCurrentProviderAdjustments(int academicYear) { logger.LogInfo("Getting Current Provider Adjustments - Getting Token"); var token = await GetToken(); logger.LogInfo("Token retrieved"); var providerAdjustments = new List <ProviderAdjustment>(); var pageNumber = 1; while (true) { var request = new HttpRequestMessage(HttpMethod.Get, $"api/v1/Eas/{academicYear}?pagenumber={pageNumber}&pagesize={pageSize}"); request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token); logger.LogInfo($"Getting page {pageNumber} of data from API"); var httpResponse = await client.SendAsync(request).ConfigureAwait(false); logger.LogInfo($"Successfully connected to the API"); var responseContent = await httpResponse.Content.ReadAsStringAsync(); logger.LogDebug($"Response code: {httpResponse.StatusCode}, Reason: {httpResponse.ReasonPhrase}, " + $"Request: {httpResponse.RequestMessage.RequestUri}"); if (httpResponse.IsSuccessStatusCode) { var batch = JsonConvert.DeserializeObject <List <ProviderAdjustment> >(responseContent); if (batch.Count == 0) { logger.LogInfo($"No messages on page {pageNumber}"); break; } logger.LogInfo($"Successfully retrieved {batch.Count} records from API"); providerAdjustments.AddRange(batch); } else { logger.LogError($"Error getting EAS records: {responseContent}, {httpResponse}"); throw new InvalidOperationException($"Error getting EAS records: {responseContent}"); } pageNumber++; } logger.LogInfo($"Finished reading records from the API. Got {providerAdjustments.Count} records"); return(providerAdjustments); }
private static async Task RunLevyAccountImport(IEndpointInstanceFactory endpointInstanceFactory, IScheduledJobsConfiguration config, IPaymentLogger log) { try { var command = new ImportEmployerAccounts(); var endpointInstance = await endpointInstanceFactory.GetEndpointInstance().ConfigureAwait(false); await endpointInstance.Send(config.LevyAccountBalanceEndpoint, command).ConfigureAwait(false); } catch (Exception e) { log.LogError("Error in LevyAccountImport", e); throw; } }
/// <summary> /// Optional override to create listeners (e.g., TCP, HTTP) for this service replica to handle client or user requests. /// </summary> /// <returns>A collection of listeners.</returns> protected override IEnumerable <ServiceInstanceListener> CreateServiceInstanceListeners() { try { return(new List <ServiceInstanceListener> { new ServiceInstanceListener(context => lifetimeScope.Resolve <IStatelessServiceBusBatchCommunicationListener>()) }); } catch (Exception e) { logger.LogError($"Error starting the service instance listener: {e.Message}", e); throw; } }
public async Task <bool> HandleAsync(JobContextMessage message, CancellationToken cancellationToken) { try { logger.LogDebug("Getting task type from period end message."); var taskType = GetTask(message); logger.LogDebug("Got period end type now create the period end event."); var periodEndEvent = CreatePeriodEndEvent(taskType); logger.LogDebug($"Created period end event. Type: {periodEndEvent.GetType().Name}"); periodEndEvent.JobId = message.JobId; periodEndEvent.CollectionPeriod = new CollectionPeriod { AcademicYear = Convert.ToInt16(GetMessageValue(message, JobContextMessageConstants.KeyValuePairs.CollectionYear)), Period = Convert.ToByte(GetMessageValue(message, JobContextMessageConstants.KeyValuePairs.ReturnPeriod)) }; logger.LogDebug($"Got period end event: {periodEndEvent.ToJson()}"); await RecordPeriodEndJob(taskType, periodEndEvent).ConfigureAwait(false); var endpointInstance = await endpointInstanceFactory.GetEndpointInstance(); await endpointInstance.Publish(periodEndEvent); logger.LogInfo($"Finished publishing the period end event. Name: {periodEndEvent.GetType().Name}, JobId: {periodEndEvent.JobId}, Collection Period: {periodEndEvent.CollectionPeriod.Period}-{periodEndEvent.CollectionPeriod.AcademicYear}."); // TODO: This is a temporary workaround to enable the PeriodEndStart and PeriodEndStop messages to return true as otherwise the service will // TODO: just hang as there is nothing implemented to handle the Start and Stop events and so the job status service will never get a completion and so this will never return true. // PV2-1345 will handle PeriodEndStart // PeriodEndStoppedEvent will be handled by the PeriodEndStoppedEventHandler which in turn is handled by the ProcessProviderMonthEndCommandHandler but we don't want to wait for it if (periodEndEvent is PeriodEndStartedEvent || periodEndEvent is PeriodEndStoppedEvent) { logger.LogDebug("Returning as this is either a PeriodEndStart or PeriodEndStop event"); return(true); } await jobStatusService.WaitForJobToFinish(message.JobId, cancellationToken); return(true); } catch (Exception ex) { logger.LogError($"Failed to process job context message. Message: {message.ToJson()}", ex); throw; } }
public async Task Handle(SubmissionSucceededEvent message, IMessageHandlerContext context) { var logString = $"{typeof(SubmissionSucceededEvent).Name}. UKPRN: {message.Ukprn} {message.AcademicYear}-R{message.CollectionPeriod:D2}, ILR Submission: {message.IlrSubmissionDateTime:s}, Job ID: {message.JobId}"; logger.LogInfo("Handling " + logString); try { await submissionEventProcessor.ProcessSubmissionSucceededEvent(message).ConfigureAwait(false); logger.LogInfo("Finished handling " + logString); } catch (Exception ex) { logger.LogError($"Error handling {logString}. {ex.Message}"); throw; } }
public async Task StartJob(long jobId, long ukprn, DateTime ilrSubmissionTime, short collectionYear, byte collectionPeriod, List <GeneratedMessage> generatedMessages, DateTimeOffset startTime) { logger.LogVerbose($"Sending request to record start of earnings job. Job Id: {jobId}, Ukprn: {ukprn}"); try { var batchSize = 1000; //TODO: this should come from config List <GeneratedMessage> batch; var providerEarningsEvent = new RecordEarningsJob { StartTime = startTime, JobId = jobId, Ukprn = ukprn, IlrSubmissionTime = ilrSubmissionTime, CollectionYear = collectionYear, CollectionPeriod = collectionPeriod, GeneratedMessages = generatedMessages.Take(batchSize).ToList(), LearnerCount = generatedMessages.Count }; var jobsEndpointName = config.GetSettingOrDefault("Monitoring_JobsService_EndpointName", "sfa-das-payments-monitoring-jobs"); var partitionedEndpointName = $"{jobsEndpointName}{partitionName.PartitionNameForJob(jobId, ukprn)}"; logger.LogVerbose($"Endpoint for RecordEarningsJob for Job Id {jobId} is `{partitionedEndpointName}`"); await messageSession.Send(partitionedEndpointName, providerEarningsEvent).ConfigureAwait(false); var skip = batchSize; while ((batch = generatedMessages.Skip(skip).Take(1000).ToList()).Count > 0) { skip += batchSize; var providerEarningsAdditionalMessages = new RecordEarningsJobAdditionalMessages { JobId = jobId, GeneratedMessages = batch, }; await messageSession.Send(partitionedEndpointName, providerEarningsAdditionalMessages).ConfigureAwait(false); } logger.LogDebug($"Sent request(s) to record start of earnings job. Job Id: {jobId}, Ukprn: {ukprn}"); } catch (Exception ex) { logger.LogError($"Failed to send the request to record the earnings job. Job: {jobId}, Error: {ex.Message}", ex); throw; } }
protected override IEnumerable <ServiceReplicaListener> CreateServiceReplicaListeners() { try { partitionEndpointName = ((NamedPartitionInformation)Partition.PartitionInfo).Name; var batchListener = lifetimeScope.Resolve <IServiceBusBatchCommunicationListener>(); batchListener.EndpointName += partitionEndpointName; var serviceListener = new ServiceReplicaListener(context => batchListener); return(new List <ServiceReplicaListener> { serviceListener }); } catch (Exception e) { logger.LogError($"Error: {e.Message}", e); throw; } }
public async Task PerformExportPaymentsAndEarningsToV1(CollectionPeriod collectionPeriod) { logger.LogVerbose($"Started V1 payments export for collection period {collectionPeriod}"); while (true) { int page = -1; try { page = await paymentExportProgressCache.GetPage(collectionPeriod.AcademicYear, collectionPeriod.Period); logger.LogVerbose($"Starting with page: {page}"); var payments = providerPaymentsRepository.GetMonthEndPayments(collectionPeriod, exportBatchSize, page); if (payments.Count == 0) { logger.LogVerbose($"Finished exporting payments to V1 for collection period: {collectionPeriod}"); break; } logger.LogVerbose($"Found {payments.Count} payments to process"); var result = paymentMapper.MapV2Payments(payments); await legacyPaymentsRepository .WritePaymentInformation(result.payments, result.requiredPayments, result.earnings) .ConfigureAwait(false); logger.LogVerbose($"Completed write for page: {page} for collection period: {collectionPeriod}"); await paymentExportProgressCache .IncrementPage(collectionPeriod.AcademicYear, collectionPeriod.Period) .ConfigureAwait(false); } catch (Exception e) { logger.LogError($"Error processing page: {page} during V1 legacy export", e); throw; } } logger.LogVerbose($"Completed V1 payments export for collection period {collectionPeriod}"); }
public async Task StoreEmployerProviderPriority(EmployerChangedProviderPriority providerPriorityEvent) { try { int order = 1; var paymentPriorities = new List <EmployerProviderPriorityModel>(); foreach (var providerUkprn in providerPriorityEvent.OrderedProviders) { paymentPriorities.Add(new EmployerProviderPriorityModel { Ukprn = providerUkprn, EmployerAccountId = providerPriorityEvent.EmployerAccountId, Order = order }); order++; } using (var scope = new TransactionScope(TransactionScopeOption.Required, TransactionScopeAsyncFlowOption.Enabled)) { paymentLogger.LogDebug($"Replacing Previous EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}"); await levyFundingSourceRepository.ReplaceEmployerProviderPriorities(providerPriorityEvent.EmployerAccountId, paymentPriorities).ConfigureAwait(false); paymentLogger.LogDebug($"Successfully Replaced Previous EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}"); paymentLogger.LogDebug($"Adding EmployerProviderPriority to Cache for Account Id {providerPriorityEvent.EmployerAccountId}"); await employerProviderPriorities.AddOrReplace(CacheKeys.EmployerPaymentPriorities, paymentPriorities).ConfigureAwait(false); paymentLogger.LogInfo($"Successfully Add EmployerProviderPriority to Cache for Account Id {providerPriorityEvent.EmployerAccountId}"); scope.Complete(); } } catch (Exception e) { paymentLogger.LogError($"Error while updating EmployerProviderPriority for Account Id {providerPriorityEvent.EmployerAccountId}", e); throw; } }