< Summary

Information
Class: Services.BackgroundJobsServices.BackgroundJobLoggingService
Assembly: Services
File(s): /home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BackgroundJobsServices/BackgroundJobLoggingService.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 191
Coverable lines: 191
Total lines: 322
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 112
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/AppRepository/BackgroundJobsServices/BackgroundJobLoggingService.cs

#LineLine coverage
 1using System.Diagnostics;
 2using Microsoft.EntityFrameworkCore;
 3using Newtonsoft.Json;
 4using OzonDomains.Models;
 5using OzonRepositories.Context;
 6
 7namespace Services.BackgroundJobsServices;
 8
 9public interface IBackgroundJobLoggingService
 10{
 11    Task<long> StartExecutionAsync(int? scheduleId, string jobType, string triggerType, CancellationToken cancellationTo
 12    Task CompleteExecutionAsync(long executionId, CancellationToken cancellationToken = default);
 13    Task FailExecutionAsync(long executionId, string errorMessage, string? stackTrace = null, CancellationToken cancella
 14    Task UpdateExecutionStatsAsync(long executionId, int totalOrders = 0, int matchedOrders = 0, int processedOrders = 0
 15
 16    Task<long> StartStepAsync(long executionId, int stepNumber, string stepName, object? inputData = null, CancellationT
 17    Task CompleteStepAsync(long stepId, object? outputData = null, CancellationToken cancellationToken = default);
 18    Task FailStepAsync(long stepId, string errorMessage, CancellationToken cancellationToken = default);
 19
 20    Task<long> LogReportLoadAsync(long executionId, long? stepId, int ozonClientId, DateTime periodFrom, DateTime period
 21    Task UpdateReportLoadAsync(long reportLoadId, string? fileName = null, string? fileUrl = null, long? fileSizeBytes =
 22
 23    Task<long> LogOrderMatchAsync(long executionId, long? stepId, long? reportLoadId, string orderNumber, string article
 24    Task BulkLogOrderMatchesAsync(IEnumerable<BackgroundOrderMatch> matches, CancellationToken cancellationToken = defau
 25
 26    Task<long> LogTransactionResultAsync(long executionId, long? stepId, long? orderMatchId, int orderId, string? wareho
 27    Task UpdateTransactionResultAsync(long resultId, int? transactionId = null, string? oneCDocumentId = null, string? o
 28    Task BulkUpdateTransactionResultsAsync(IEnumerable<(long resultId, int? transactionId, string? oneCDocumentId, strin
 29
 30    Task<BackgroundJobExecution?> GetExecutionAsync(long executionId, CancellationToken cancellationToken = default);
 31    Task<List<BackgroundJobStep>> GetExecutionStepsAsync(long executionId, CancellationToken cancellationToken = default
 32}
 33
 34public class BackgroundJobLoggingService : IBackgroundJobLoggingService
 35{
 36    private readonly IDbContextFactory<ApplicationDbContext> _contextFactory;
 37
 038    public BackgroundJobLoggingService(IDbContextFactory<ApplicationDbContext> contextFactory)
 39    {
 040        _contextFactory = contextFactory;
 041    }
 42
 43    public async Task<long> StartExecutionAsync(int? scheduleId, string jobType, string triggerType, CancellationToken c
 44    {
 045        await using var context = _contextFactory.CreateDbContext();
 46
 047        var execution = new BackgroundJobExecution
 048        {
 049            ScheduleId = scheduleId,
 050            JobType = jobType,
 051            Status = "Running",
 052            TriggerType = triggerType,
 053            StartedAt = DateTime.UtcNow
 054        };
 55
 056        context.BackgroundJobExecutions.Add(execution);
 057        await context.SaveChangesAsync(cancellationToken);
 58
 059        return execution.Id;
 060    }
 61
 62    public async Task CompleteExecutionAsync(long executionId, CancellationToken cancellationToken = default)
 63    {
 064        await using var context = _contextFactory.CreateDbContext();
 65
 066        var execution = await context.BackgroundJobExecutions.FindAsync(new object[] { executionId }, cancellationToken)
 067        if (execution == null) return;
 68
 069        execution.CompletedAt = DateTime.UtcNow;
 070        execution.DurationMs = (long)(execution.CompletedAt.Value - execution.StartedAt).TotalMilliseconds;
 71
 072        if (execution.FailedOrders == 0)
 073            execution.Status = "Completed";
 074        else if (execution.SuccessfulOrders > 0)
 075            execution.Status = "PartialSuccess";
 76        else
 077            execution.Status = "Failed";
 78
 079        execution.CompletedSteps = await context.BackgroundJobSteps
 080            .Where(s => s.ExecutionId == executionId && s.Status == "Completed")
 081            .CountAsync(cancellationToken);
 82
 083        await context.SaveChangesAsync(cancellationToken);
 084    }
 85
 86    public async Task FailExecutionAsync(long executionId, string errorMessage, string? stackTrace = null, CancellationT
 87    {
 088        await using var context = _contextFactory.CreateDbContext();
 89
 090        var execution = await context.BackgroundJobExecutions.FindAsync(new object[] { executionId }, cancellationToken)
 091        if (execution == null) return;
 92
 093        execution.CompletedAt = DateTime.UtcNow;
 094        execution.DurationMs = (long)(execution.CompletedAt.Value - execution.StartedAt).TotalMilliseconds;
 095        execution.Status = "Failed";
 096        execution.ErrorMessage = errorMessage;
 097        execution.ErrorStackTrace = stackTrace;
 98
 099        await context.SaveChangesAsync(cancellationToken);
 0100    }
 101
 102    public async Task UpdateExecutionStatsAsync(long executionId, int totalOrders = 0, int matchedOrders = 0, int proces
 103    {
 0104        await using var context = _contextFactory.CreateDbContext();
 105
 0106        var execution = await context.BackgroundJobExecutions.FindAsync(new object[] { executionId }, cancellationToken)
 0107        if (execution == null) return;
 108
 0109        if (totalOrders > 0) execution.TotalOrders = totalOrders;
 0110        if (matchedOrders > 0) execution.MatchedOrders = matchedOrders;
 0111        if (processedOrders > 0) execution.ProcessedOrders = processedOrders;
 0112        if (successfulOrders > 0) execution.SuccessfulOrders = successfulOrders;
 0113        if (failedOrders > 0) execution.FailedOrders = failedOrders;
 114
 0115        await context.SaveChangesAsync(cancellationToken);
 0116    }
 117
 118    public async Task<long> StartStepAsync(long executionId, int stepNumber, string stepName, object? inputData = null, 
 119    {
 0120        await using var context = _contextFactory.CreateDbContext();
 121
 0122        var step = new BackgroundJobStep
 0123        {
 0124            ExecutionId = executionId,
 0125            StepNumber = stepNumber,
 0126            StepName = stepName,
 0127            Status = "Running",
 0128            StartedAt = DateTime.UtcNow,
 0129            InputData = inputData != null ? JsonConvert.SerializeObject(inputData) : null
 0130        };
 131
 0132        context.BackgroundJobSteps.Add(step);
 0133        await context.SaveChangesAsync(cancellationToken);
 134
 0135        return step.Id;
 0136    }
 137
 138    public async Task CompleteStepAsync(long stepId, object? outputData = null, CancellationToken cancellationToken = de
 139    {
 0140        await using var context = _contextFactory.CreateDbContext();
 141
 0142        var step = await context.BackgroundJobSteps.FindAsync(new object[] { stepId }, cancellationToken);
 0143        if (step == null) return;
 144
 0145        step.CompletedAt = DateTime.UtcNow;
 0146        step.DurationMs = (long)(step.CompletedAt.Value - step.StartedAt).TotalMilliseconds;
 0147        step.Status = "Completed";
 0148        step.OutputData = outputData != null ? JsonConvert.SerializeObject(outputData) : null;
 149
 0150        await context.SaveChangesAsync(cancellationToken);
 0151    }
 152
 153    public async Task FailStepAsync(long stepId, string errorMessage, CancellationToken cancellationToken = default)
 154    {
 0155        await using var context = _contextFactory.CreateDbContext();
 156
 0157        var step = await context.BackgroundJobSteps.FindAsync(new object[] { stepId }, cancellationToken);
 0158        if (step == null) return;
 159
 0160        step.CompletedAt = DateTime.UtcNow;
 0161        step.DurationMs = (long)(step.CompletedAt.Value - step.StartedAt).TotalMilliseconds;
 0162        step.Status = "Failed";
 0163        step.ErrorMessage = errorMessage;
 164
 0165        await context.SaveChangesAsync(cancellationToken);
 0166    }
 167
 168    public async Task<long> LogReportLoadAsync(long executionId, long? stepId, int ozonClientId, DateTime periodFrom, Da
 169    {
 0170        await using var context = _contextFactory.CreateDbContext();
 171
 0172        var reportLoad = new BackgroundReportLoad
 0173        {
 0174            ExecutionId = executionId,
 0175            StepId = stepId,
 0176            OzonClientId = ozonClientId,
 0177            ReportCode = reportCode,
 0178            ReportPeriodFrom = periodFrom,
 0179            ReportPeriodTo = periodTo,
 0180            Status = "Requested",
 0181            CreatedAt = DateTime.UtcNow
 0182        };
 183
 0184        context.BackgroundReportLoads.Add(reportLoad);
 0185        await context.SaveChangesAsync(cancellationToken);
 186
 0187        return reportLoad.Id;
 0188    }
 189
 190    public async Task UpdateReportLoadAsync(long reportLoadId, string? fileName = null, string? fileUrl = null, long? fi
 191    {
 0192        await using var context = _contextFactory.CreateDbContext();
 193
 0194        var reportLoad = await context.BackgroundReportLoads.FindAsync(new object[] { reportLoadId }, cancellationToken)
 0195        if (reportLoad == null) return;
 196
 0197        if (fileName != null) reportLoad.FileName = fileName;
 0198        if (fileUrl != null) reportLoad.FileUrl = fileUrl;
 0199        if (fileSizeBytes.HasValue) reportLoad.FileSizeBytes = fileSizeBytes.Value;
 0200        if (totalRows.HasValue) reportLoad.TotalRows = totalRows.Value;
 0201        if (rowsWithRequiredData.HasValue) reportLoad.RowsWithRequiredData = rowsWithRequiredData.Value;
 0202        if (uniqueOrderNumbers.HasValue) reportLoad.UniqueOrderNumbers = uniqueOrderNumbers.Value;
 0203        if (status != null) reportLoad.Status = status;
 0204        if (errorMessage != null) reportLoad.ErrorMessage = errorMessage;
 205
 0206        await context.SaveChangesAsync(cancellationToken);
 0207    }
 208
 209    public async Task<long> LogOrderMatchAsync(long executionId, long? stepId, long? reportLoadId, string orderNumber, s
 210    {
 0211        await using var context = _contextFactory.CreateDbContext();
 212
 0213        var match = new BackgroundOrderMatch
 0214        {
 0215            ExecutionId = executionId,
 0216            StepId = stepId,
 0217            ReportLoadId = reportLoadId,
 0218            OrderNumber = orderNumber,
 0219            Article = article,
 0220            OrderId = orderId,
 0221            OrderStatus = orderStatus,
 0222            IsMatchedInDb = isMatchedInDb,
 0223            IsEligibleForProcessing = isEligibleForProcessing,
 0224            RejectionReason = rejectionReason,
 0225            CreatedAt = DateTime.UtcNow
 0226        };
 227
 0228        context.BackgroundOrderMatches.Add(match);
 0229        await context.SaveChangesAsync(cancellationToken);
 230
 0231        return match.Id;
 0232    }
 233
 234    public async Task BulkLogOrderMatchesAsync(IEnumerable<BackgroundOrderMatch> matches, CancellationToken cancellation
 235    {
 0236        await using var context = _contextFactory.CreateDbContext();
 237
 0238        context.BackgroundOrderMatches.AddRange(matches);
 0239        await context.SaveChangesAsync(cancellationToken);
 0240    }
 241
 242    public async Task<long> LogTransactionResultAsync(long executionId, long? stepId, long? orderMatchId, int orderId, s
 243    {
 0244        await using var context = _contextFactory.CreateDbContext();
 245
 0246        var result = new BackgroundTransactionResult
 0247        {
 0248            ExecutionId = executionId,
 0249            StepId = stepId,
 0250            OrderMatchId = orderMatchId,
 0251            OrderId = orderId,
 0252            WarehouseName = warehouseName,
 0253            TransactionId = transactionId,
 0254            Status = status,
 0255            Comment = comment,
 0256            IsAutomated = true,
 0257            CreatedAt = DateTime.UtcNow
 0258        };
 259
 0260        context.BackgroundTransactionResults.Add(result);
 0261        await context.SaveChangesAsync(cancellationToken);
 262
 0263        return result.Id;
 0264    }
 265
 266    public async Task UpdateTransactionResultAsync(long resultId, int? transactionId = null, string? oneCDocumentId = nu
 267    {
 0268        await using var context = _contextFactory.CreateDbContext();
 269
 0270        var result = await context.BackgroundTransactionResults.FindAsync(new object[] { resultId }, cancellationToken);
 0271        if (result == null) return;
 272
 0273        if (transactionId.HasValue) result.TransactionId = transactionId.Value;
 0274        if (oneCDocumentId != null) result.OneCDocumentId = oneCDocumentId;
 0275        if (oneCDocumentNumber != null) result.OneCDocumentNumber = oneCDocumentNumber;
 0276        if (status != null) result.Status = status;
 0277        if (errorMessage != null) result.ErrorMessage = errorMessage;
 0278        if (comment != null) result.Comment = comment;
 0279        if (isPosted.HasValue) result.IsPosted = isPosted.Value;
 280
 0281        await context.SaveChangesAsync(cancellationToken);
 0282    }
 283
 284    public async Task BulkUpdateTransactionResultsAsync(IEnumerable<(long resultId, int? transactionId, string? oneCDocu
 285    {
 0286        await using var context = _contextFactory.CreateDbContext();
 287
 0288        foreach (var update in updates)
 289        {
 0290            var result = await context.BackgroundTransactionResults.FindAsync(new object[] { update.resultId }, cancella
 0291            if (result == null) continue;
 292
 0293            if (update.transactionId.HasValue) result.TransactionId = update.transactionId.Value;
 0294            if (update.oneCDocumentId != null) result.OneCDocumentId = update.oneCDocumentId;
 0295            if (update.oneCDocumentNumber != null) result.OneCDocumentNumber = update.oneCDocumentNumber;
 0296            if (update.status != null) result.Status = update.status;
 0297            if (update.errorMessage != null) result.ErrorMessage = update.errorMessage;
 0298            if (update.comment != null) result.Comment = update.comment;
 0299            if (update.isPosted.HasValue) result.IsPosted = update.isPosted.Value;
 0300        }
 301
 0302        await context.SaveChangesAsync(cancellationToken);
 0303    }
 304
 305    public async Task<BackgroundJobExecution?> GetExecutionAsync(long executionId, CancellationToken cancellationToken =
 306    {
 0307        await using var context = _contextFactory.CreateDbContext();
 0308        return await context.BackgroundJobExecutions
 0309            .AsNoTracking()
 0310            .FirstOrDefaultAsync(e => e.Id == executionId, cancellationToken);
 0311    }
 312
 313    public async Task<List<BackgroundJobStep>> GetExecutionStepsAsync(long executionId, CancellationToken cancellationTo
 314    {
 0315        await using var context = _contextFactory.CreateDbContext();
 0316        return await context.BackgroundJobSteps
 0317            .AsNoTracking()
 0318            .Where(s => s.ExecutionId == executionId)
 0319            .OrderBy(s => s.StepNumber)
 0320            .ToListAsync(cancellationToken);
 0321    }
 322}