Implemented scheduling service and first two jobs

This commit is contained in:
2026-10-28 17:01:28 +02:00
parent 6114d8f457
commit 7f686fa8c6
20 changed files with 304 additions and 112 deletions
@@ -0,0 +1,77 @@
using PostFundManagement.Application.Abstractions.Services;
using PostFundManagement.Application.Services.Communications;
using PostFundManagement.Domain;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Events;
public sealed class LateProjectEvent : IEvent
{
public Guid Id { get; set; } = Guid.CreateVersion7();
public string Name { get; set; } = nameof(LateProjectEvent);
public DateTimeOffset EnqueueAt { get; set; } = DateTimeOffset.UtcNow;
public string CorrelationId { get; set; } = "lateproject-reminder";
public static LateProjectEvent Create() => new();
}
public sealed class LateProjectEventHandler(IDbContextFactory<ApplicationDbContext> contextFactory,
ICommunicationsService service) : INotificationHandler<LateProjectEvent>
{
readonly int lateDays = 3;
public async ValueTask Handle(LateProjectEvent notification, CancellationToken cancellationToken)
{
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var lateMilestones = await context.Milestones
.AsNoTracking()
.Include(i => i.Project!.Programme!.Portfolio!.Organisation!.User)
.Where(m => (DateTime.UtcNow - m.Project!.StartedAt!).Value.TotalDays < lateDays)
.OrderBy(o => o.CreatedAt)
.GroupBy(g => g.ProjectId)
.AsSplitQuery()
.ToListAsync(cancellationToken);
if (lateMilestones is null) return;
using var htmlTemplateReader = new StreamReader(Assembly.GetAssembly(typeof(IDomain))?
.GetManifestResourceStream("PostFundManagement.Domain.Templates.lateprojectsmilestones.html")!);
var template = await htmlTemplateReader.ReadToEndAsync(cancellationToken);
foreach (var group in lateMilestones)
{
if (!group.Any()) continue;
var project = group.FirstOrDefault()?.Project;
if (project is null) continue;
var mostLateMilestone = group.OrderBy(m => m.DueAt).FirstOrDefault();
var missedMilestone = group.Where(m => DateTime.UtcNow > m.DueAt).FirstOrDefault();
var messageBody = template;
messageBody = messageBody.Replace("[ProjectName]", project.Name);
messageBody = messageBody.Replace("[ProjectStartDate]", $"{project.StartedAt:yyyy-MM-dd}");
messageBody = messageBody.Replace("[ProjectEndDate]", $"{project.EndedAt:yyyy-MM-dd}");
messageBody = messageBody.Replace("[TotalLateMiletones]", $"{group.Count()}");
// TODO: output information of most late milestone
// TODO: output information of milestones already missed
var organisation = mostLateMilestone?.Project?.Programme?.Portfolio?.Organisation;
if (organisation is null) continue;
var notificationRequest = new CreateNotificationRequest(organisation.Id, organisation.User!.Id, NotificationPlatform.Email,
"Project Status Update", organisation.User!.Email, messageBody, NotificationStatus.Queued);
_ = await service.CreateNotificationAsync(notificationRequest, SystemUser, cancellationToken);
}
}
}
@@ -0,0 +1,122 @@
using PostFundManagement.Application.Services.Shared;
using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Infrastructure.Database;
namespace PostFundManagement.Application.Events;
public sealed class ProcessEmailEvent : IEvent
{
public Guid Id { get; set; } = Guid.CreateVersion7();
public string Name { get; set; } = nameof(ProcessEmailEvent);
public DateTimeOffset EnqueueAt { get; set; } = DateTimeOffset.UtcNow;
public string CorrelationId { get; set; } = "email-processor";
public static ProcessEmailEvent Create() => new();
}
public sealed class ProcessEmailEventHandler(IDbContextFactory<ApplicationDbContext> contextFactory,
IFeatureManager featureManager, EmailService emailService, ISkorubaUserService skorubaUserService) : INotificationHandler<ProcessEmailEvent>
{
const int maxBatch = 100;
public async ValueTask Handle(ProcessEmailEvent notification, CancellationToken cancellationToken)
{
if (!await featureManager.IsEnabledAsync(FeatureEmailProcessor)) return;
await using var context = await contextFactory.CreateDbContextAsync(cancellationToken);
var outgoing = await context.Notifications.AsNoTracking()
.Include(i => i.Organisation)
.Include(i => i.RecipientUser)
.Include(i => i.Tenant)
.Where(n => n.Status == Domain.NotificationStatus.Queued)
.OrderByDescending(o => o.CreatedAt)
.Take(maxBatch)
.ToListAsync(cancellationToken);
if (outgoing?.Count == 0) return;
if (emailService.Status is not (Domain.EmailStatuses.Connected or Domain.EmailStatuses.Success))
await emailService.ConnectAsync(cancellationToken);
var failedTransmissions = new List<(long notificationId, string? error)>();
foreach (var enqueuedMessage in outgoing!)
{
var userClaimResult = await skorubaUserService.GetUserClaimsAsync(enqueuedMessage.RecipientUser!.Id, cancellationToken: cancellationToken);
if (userClaimResult.IsFailed)
{
failedTransmissions.Add((enqueuedMessage.Id, "Failed to retrieve user claims"));
continue;
}
var name = userClaimResult.Value.FirstOrDefault(c => c.ClaimType == "given_name")?.ClaimValue ?? enqueuedMessage.Organisation!.Name;
var surname = userClaimResult.Value.FirstOrDefault(c => c.ClaimType == "family_name")?.ClaimValue ?? string.Empty;
var email = enqueuedMessage.RecipientUser?.Email ?? enqueuedMessage.Organisation?.Email ?? enqueuedMessage.Destination ?? string.Empty;
if (string.IsNullOrWhiteSpace(email))
{
failedTransmissions.Add((enqueuedMessage.Id, "Could not resolve destination email address"));
continue;
}
var message = new Domain.Models.Email.Message
{
Sender = new Domain.Models.Email.Party
{
Address = "noreply@ifritechnologies.co.za",
Name = "Post Fund Management"
},
Recipient = new Domain.Models.Email.Party
{
Address = email,
Name = string.IsNullOrWhiteSpace(surname)
? name : $"{name} {surname}"
},
Subject = enqueuedMessage.Subject,
Body = new Domain.Models.Email.Body
{
Properties = new Domain.Models.Email.BodyProperties
{
HasAttachments = false,
IsHtml = true
},
Message = enqueuedMessage.Message
}
};
var response = await emailService.SendEmailAsync(message, cancellationToken);
if (response.IsFailed || response.Value.Status is not (Domain.EmailStatuses.Connected or Domain.EmailStatuses.Success))
{
failedTransmissions.Add((enqueuedMessage.Id, $"Error: {response.Value.Error}"));
continue;
}
}
foreach (var (notificationId, error) in failedTransmissions)
await context.Notifications.Where(n => n.Id == notificationId)
.ExecuteUpdateAsync(p => p
.SetProperty(u => u.Status, Domain.NotificationStatus.Failed)
.SetProperty(u => u.Error, error), cancellationToken);
var failedIds = failedTransmissions.Select(f => f.notificationId).ToList();
foreach (var successMessage in outgoing)
{
if (failedIds.Contains(successMessage.Id)) continue;
await context.Notifications.Where(n => n.Id == successMessage.Id)
.ExecuteUpdateAsync(p => p
.SetProperty(u => u.Status, Domain.NotificationStatus.Sent)
.SetProperty(u => u.Error, string.Empty), cancellationToken);
}
}
}
@@ -15,7 +15,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<ApplicantData[]>> GetApplicantDataAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => public async Task<Result<ApplicantData[]>> GetApplicantDataAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<ApplicantData[]>>>)(async () => await Result.Try((Func<Task<Result<ApplicantData[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetApplicantDataAsync(applicantUserId, cancellationToken); return await service.GetApplicantDataAsync(applicantUserId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getapplicantdata-{applicantUserId}").Value; var cacheKey = HashService.ToMd5Hash($"getapplicantdata-{applicantUserId}").Value;
@@ -37,7 +37,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => public async Task<Result<Invite>> GetApplicantInviteAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Invite>>>)(async () => await Result.Try((Func<Task<Result<Invite>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetApplicantInviteAsync(applicantUserId, cancellationToken); return await service.GetApplicantInviteAsync(applicantUserId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{applicantUserId}").Value; var cacheKey = HashService.ToMd5Hash($"getapplicantinvite-{applicantUserId}").Value;
@@ -59,7 +59,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) => public async Task<Result<Invite[]>> GetApplicantInvitesAsync(Guid applicantUserId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Invite[]>>>)(async () => await Result.Try((Func<Task<Result<Invite[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken); return await service.GetApplicantInvitesAsync(applicantUserId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getapplicantinvites-{applicantUserId}").Value; var cacheKey = HashService.ToMd5Hash($"getapplicantinvites-{applicantUserId}").Value;
@@ -83,7 +83,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Invite[]>> GetInvitesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Invite[]>>>)(async () => await Result.Try((Func<Task<Result<Invite[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetInvitesAsync(pagination, cancellationToken); return await service.GetInvitesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getinvites-{pagination.Page}-{pagination.PageSize}").Value;
@@ -107,7 +107,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<Notification>> GetNotificationAsync(string notificationIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Notification>> GetNotificationAsync(string notificationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Notification>>>)(async () => await Result.Try((Func<Task<Result<Notification>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetNotificationAsync(notificationIdHash, cancellationToken); return await service.GetNotificationAsync(notificationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getnotification-{notificationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getnotification-{notificationIdHash}").Value;
@@ -131,7 +131,7 @@ public sealed class CommunicationsCacheService(CommunicationsService service, ID
public async Task<Result<Notification[]>> GetNotificationsAsync(string organisationIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Notification[]>> GetNotificationsAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Notification[]>>>)(async () => await Result.Try((Func<Task<Result<Notification[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetNotificationsAsync(organisationIdHash, cancellationToken); return await service.GetNotificationsAsync(organisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getnotifications-{organisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getnotifications-{organisationIdHash}").Value;
@@ -1,21 +0,0 @@
using PostFundManagement.Application.Abstractions;
using PostFundManagement.Domain.Abstractions;
namespace PostFundManagement.Application.Services.Communications.Events;
public class SyncUserEvent : EventBase, IEvent
{
public string Name { get; set; } = nameof(SyncUserEvent);
public static SyncUserEvent Create() => new();
}
public class SyncUserEventHandler(ILogger<SyncUserEvent> logger) : INotificationHandler<SyncUserEvent>
{
public ValueTask Handle(SyncUserEvent notification, CancellationToken cancellationToken)
{
logger.LogInformation("Integration Sync executed. Correlation ID: {CorrelationId}", notification.CorrelationId);
return ValueTask.CompletedTask;
}
}
@@ -21,7 +21,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Evidence>> GetEvidenceAsync(string evidenceId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Evidence>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Evidence>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetEvidenceAsync(evidenceId, cancellationToken); return await service.GetEvidenceAsync(evidenceId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value; var cacheKey = HashService.ToMd5Hash($"getevidence-{evidenceId}").Value;
@@ -45,7 +45,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Evidence[]>> GetEvidenceFilesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetEvidenceFilesAsync(pagination, cancellationToken); return await service.GetEvidenceFilesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getevidencefiles-{pagination.Page}-{pagination.PageSize}").Value;
@@ -69,7 +69,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<string>> GetEvidenceUrlAsync(string evidenceIdHash, CancellationToken cancellationToken = default) => public async Task<Result<string>> GetEvidenceUrlAsync(string evidenceIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<string>>>)(async () => await Result.Try((Func<Task<Result<string>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetEvidenceUrlAsync(evidenceIdHash, cancellationToken); return await service.GetEvidenceUrlAsync(evidenceIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getevidenceurl-{evidenceIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getevidenceurl-{evidenceIdHash}").Value;
@@ -93,7 +93,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) => public async Task<Result<Indicator>> GetIndicatorAsync(string indicatorId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Indicator>>>)(async () => await Result.Try((Func<Task<Result<Indicator>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetIndicatorAsync(indicatorId, cancellationToken); return await service.GetIndicatorAsync(indicatorId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value; var cacheKey = HashService.ToMd5Hash($"getindicator-{indicatorId}").Value;
@@ -117,7 +117,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Indicator[]>> GetIndicatorsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Indicator[]>>>)(async () => await Result.Try((Func<Task<Result<Indicator[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetIndicatorsAsync(pagination, cancellationToken); return await service.GetIndicatorsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getindicators-{pagination.Page}-{pagination.PageSize}").Value;
@@ -141,7 +141,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Evidence[]>> GetMilestoneEvidencesAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken); return await service.GetMilestoneEvidencesAsync(milestoneIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestoneevidences-{milestoneIdHash}").Value;
@@ -165,7 +165,7 @@ public sealed class EvidenceCacheService(EvidenceService service, IDistributedCa
public async Task<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Evidence[]>> GetProjectEvidencesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Evidence[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken); return await service.GetProjectEvidencesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectevidences-{projectIdHash}").Value;
@@ -24,7 +24,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Disbursement>> GetDisbursementAsync(string disbursementIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Disbursement>>>)(async () => await Result.Try((Func<Task<Result<Disbursement>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetDisbursementAsync(disbursementIdHash, cancellationToken); return await service.GetDisbursementAsync(disbursementIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getdisbursement-{disbursementIdHash}").Value;
@@ -48,7 +48,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Disbursement[]>> GetDisbursementsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Disbursement[]>>>)(async () => await Result.Try((Func<Task<Result<Disbursement[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetDisbursementsAsync(pagination, cancellationToken); return await service.GetDisbursementsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getdisbursements-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
@@ -72,7 +72,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Risk>> GetRiskAsync(string riskIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Risk>>>)(async () => await Result.Try((Func<Task<Result<Risk>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetRiskAsync(riskIdHash, cancellationToken); return await service.GetRiskAsync(riskIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getrisk-{riskIdHash}").Value;
@@ -96,7 +96,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Risk[]>> GetRisksAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Risk[]>>>)(async () => await Result.Try((Func<Task<Result<Risk[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetRisksAsync(pagination, cancellationToken); return await service.GetRisksAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getrisks-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
@@ -120,7 +120,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Rule>> GetRuleAsync(string ruleIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Rule>> GetRuleAsync(string ruleIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Rule>>>)(async () => await Result.Try((Func<Task<Result<Rule>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetRuleAsync(ruleIdHash, cancellationToken); return await service.GetRuleAsync(ruleIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrisk-{ruleIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getrisk-{ruleIdHash}").Value;
@@ -144,7 +144,7 @@ public sealed class ExecutionCacheService(ExecutionService service, IDistributed
public async Task<Result<Rule[]>> GetRulesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Rule[]>> GetRulesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Rule[]>>>)(async () => await Result.Try((Func<Task<Result<Rule[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetRulesAsync(pagination, cancellationToken); return await service.GetRulesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getrules-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getrules-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
@@ -27,7 +27,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) => public async Task<Result<Dashboard>> GetDashboardAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Dashboard>>>)(async () => await Result.Try((Func<Task<Result<Dashboard>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetDashboardAsync(cancellationToken); return await service.GetDashboardAsync(cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getdashboard").Value; var cacheKey = HashService.ToMd5Hash($"getdashboard").Value;
@@ -51,7 +51,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Instrument[]>> GetInstrumentsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Instrument[]>>>)(async () => await Result.Try((Func<Task<Result<Instrument[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetInstrumentsAsync(programmeIdHash, cancellationToken); return await service.GetInstrumentsAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getinstruments").Value; var cacheKey = HashService.ToMd5Hash($"getinstruments").Value;
@@ -75,7 +75,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Organisation>> GetOrganisationAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Organisation>>>)(async () => await Result.Try((Func<Task<Result<Organisation>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetOrganisationAsync(organisationIdHash, cancellationToken); return await service.GetOrganisationAsync(organisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getorganisation-{organisationIdHash}").Value;
@@ -99,7 +99,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Organisation[]>> GetOrganisationsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Organisation[]>>>)(async () => await Result.Try((Func<Task<Result<Organisation[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetOrganisationsAsync(pagination, cancellationToken); return await service.GetOrganisationsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getorganisations-{pagination.Page}-{pagination.PageSize}").Value;
@@ -123,7 +123,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Portfolio[]>> GetOrganisationPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Portfolio[]>> GetOrganisationPorfoliosAsync(string organisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Portfolio[]>>>)(async () => await Result.Try((Func<Task<Result<Portfolio[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetOrganisationPorfoliosAsync(organisationIdHash, cancellationToken); return await service.GetOrganisationPorfoliosAsync(organisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getorganisationportfolios-{organisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getorganisationportfolios-{organisationIdHash}").Value;
@@ -147,7 +147,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Portfolio>> GetPortfolioAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Portfolio>>>)(async () => await Result.Try((Func<Task<Result<Portfolio>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetPortfolioAsync(portfolioIdHash, cancellationToken); return await service.GetPortfolioAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolio-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolio-{portfolioIdHash}").Value;
@@ -171,7 +171,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Programme[]>> GetPortfolioProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Programme[]>>>)(async () => await Result.Try((Func<Task<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken); return await service.GetPortfolioProgrammesAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolioprogrammes-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolioprogrammes-{portfolioIdHash}").Value;
@@ -195,7 +195,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Programme[]>> GetProgrammesAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Programme[]>>>)(async () => await Result.Try((Func<Task<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProgrammesAsync(portfolioIdHash, cancellationToken); return await service.GetProgrammesAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammes-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammes-{portfolioIdHash}").Value;
@@ -219,7 +219,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Tenant>> GetTenantAsync(string tenantIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Tenant>> GetTenantAsync(string tenantIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Tenant>>>)(async () => await Result.Try((Func<Task<Result<Tenant>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetTenantAsync(tenantIdHash, cancellationToken); return await service.GetTenantAsync(tenantIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"gettenant-{tenantIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"gettenant-{tenantIdHash}").Value;
@@ -243,7 +243,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<TenantOrganisation>> GetTenantOrganisationAsync(string tenantOrganisationIdHash, CancellationToken cancellationToken = default) => public async Task<Result<TenantOrganisation>> GetTenantOrganisationAsync(string tenantOrganisationIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<TenantOrganisation>>>)(async () => await Result.Try((Func<Task<Result<TenantOrganisation>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetTenantOrganisationAsync(tenantOrganisationIdHash, cancellationToken); return await service.GetTenantOrganisationAsync(tenantOrganisationIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"gettenantorganisation-{tenantOrganisationIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"gettenantorganisation-{tenantOrganisationIdHash}").Value;
@@ -267,7 +267,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<TenantOrganisation[]>> GetTenantOrganisationsAsync(string tenantIdHash, CancellationToken cancellationToken = default) => public async Task<Result<TenantOrganisation[]>> GetTenantOrganisationsAsync(string tenantIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<TenantOrganisation[]>>>)(async () => await Result.Try((Func<Task<Result<TenantOrganisation[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetTenantOrganisationsAsync(tenantIdHash, cancellationToken); return await service.GetTenantOrganisationsAsync(tenantIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"gettenantorganisations-{tenantIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"gettenantorganisations-{tenantIdHash}").Value;
@@ -294,7 +294,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Tenant[]>> GetTenantsAsync(CancellationToken cancellationToken = default) => public async Task<Result<Tenant[]>> GetTenantsAsync(CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Tenant[]>>>)(async () => await Result.Try((Func<Task<Result<Tenant[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetTenantsAsync(cancellationToken); return await service.GetTenantsAsync(cancellationToken);
var cacheKey = HashService.ToMd5Hash($"gettenants").Value; var cacheKey = HashService.ToMd5Hash($"gettenants").Value;
@@ -336,7 +336,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<Portfolio[]>> GetPorfoliosAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Portfolio[]>> GetPorfoliosAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Portfolio[]>>>)(async () => await Result.Try((Func<Task<Result<Portfolio[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetPorfoliosAsync(pagination, cancellationToken); return await service.GetPorfoliosAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfolios-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getportfolios-{pagination.Page}-{pagination.PageSize}").Value;
@@ -360,7 +360,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<decimal>> GetProgrammeValueAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async Task<Result<decimal>> GetProgrammeValueAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<decimal>>>)(async () => await Result.Try((Func<Task<Result<decimal>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProgrammeValueAsync(programmeIdHash, cancellationToken); return await service.GetProgrammeValueAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammevalue-{programmeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammevalue-{programmeIdHash}").Value;
@@ -386,7 +386,7 @@ public sealed class GovernanceCacheService(GovernanceService service, IDistribut
public async Task<Result<decimal>> GetPorfolioValueAsync(string portfolioIdHash, CancellationToken cancellationToken = default) => public async Task<Result<decimal>> GetPorfolioValueAsync(string portfolioIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<decimal>>>)(async () => await Result.Try((Func<Task<Result<decimal>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetPorfolioValueAsync(portfolioIdHash, cancellationToken); return await service.GetPorfolioValueAsync(portfolioIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getportfoliovalue-{portfolioIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getportfoliovalue-{portfolioIdHash}").Value;
@@ -27,7 +27,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Award>> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Award>>>)(async () => await Result.Try((Func<Task<Result<Award>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetAwardAsync(awardIdHash, cancellationToken); return await service.GetAwardAsync(awardIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value;
@@ -51,7 +51,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Award[]>> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Award[]>>>)(async () => await Result.Try((Func<Task<Result<Award[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetAwardsAsync(pagination, cancellationToken); return await service.GetAwardsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
@@ -75,7 +75,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Budget>> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Budget>>>)(async () => await Result.Try((Func<Task<Result<Budget>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetBudgetAsync(budgetIdHash, cancellationToken); return await service.GetBudgetAsync(budgetIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value;
@@ -99,7 +99,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Budget[]>> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Budget[]>>>)(async () => await Result.Try((Func<Task<Result<Budget[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetBudgetsAsync(pagination, cancellationToken); return await service.GetBudgetsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value;
@@ -123,7 +123,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Contract>> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Contract>>>)(async () => await Result.Try((Func<Task<Result<Contract>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetContractAsync(contractIdHash, cancellationToken); return await service.GetContractAsync(contractIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value;
@@ -147,7 +147,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Contract[]>> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Contract[]>>>)(async () => await Result.Try((Func<Task<Result<Contract[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetContractsAsync(pagination, cancellationToken); return await service.GetContractsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
@@ -171,7 +171,7 @@ public sealed class GrantsCacheService(GrantsService service, IDistributedCache
public async Task<Result<string>> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default) => public async Task<Result<string>> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<string>>>)(async () => await Result.Try((Func<Task<Result<string>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetContractUrlAsync(contractIdHash, cancellationToken); return await service.GetContractUrlAsync(contractIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcontracturl-{contractIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getcontracturl-{contractIdHash}").Value;
@@ -42,7 +42,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Activity[]>> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Activity[]>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Activity[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetActivitiesAsync(projectIdHash, cancellationToken); return await service.GetActivitiesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value;
@@ -66,7 +66,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Domain.Models.Activity>> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Domain.Models.Activity>>>)(async () => await Result.Try((Func<Task<Result<Domain.Models.Activity>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetActivityAsync(activityIdHash, cancellationToken); return await service.GetActivityAsync(activityIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value;
@@ -90,7 +90,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Beneficiary[]>> GetBeneficiariesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Beneficiary[]>> GetBeneficiariesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Beneficiary[]>>>)(async () => await Result.Try((Func<Task<Result<Beneficiary[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetBeneficiariesAsync(projectIdHash, cancellationToken); return await service.GetBeneficiariesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbeneficiaries-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getbeneficiaries-{projectIdHash}").Value;
@@ -114,7 +114,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Beneficiary>> GetBeneficiaryAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Beneficiary>> GetBeneficiaryAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Beneficiary>>>)(async () => await Result.Try((Func<Task<Result<Beneficiary>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetBeneficiaryAsync(beneficiaryIdHash, cancellationToken); return await service.GetBeneficiaryAsync(beneficiaryIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getbeneficiary-{beneficiaryIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getbeneficiary-{beneficiaryIdHash}").Value;
@@ -138,7 +138,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<ChangeRequest>> GetChangeRequestAsync(string changeRequestIdHash, CancellationToken cancellationToken = default) => public async Task<Result<ChangeRequest>> GetChangeRequestAsync(string changeRequestIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<ChangeRequest>>>)(async () => await Result.Try((Func<Task<Result<ChangeRequest>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetChangeRequestAsync(changeRequestIdHash, cancellationToken); return await service.GetChangeRequestAsync(changeRequestIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getchangerequest-{changeRequestIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getchangerequest-{changeRequestIdHash}").Value;
@@ -162,7 +162,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<ChangeRequest[]>> GetChangeRequestsAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<ChangeRequest[]>> GetChangeRequestsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<ChangeRequest[]>>>)(async () => await Result.Try((Func<Task<Result<ChangeRequest[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetChangeRequestsAsync(projectIdHash, cancellationToken); return await service.GetChangeRequestsAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getchangerequests-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getchangerequests-{projectIdHash}").Value;
@@ -186,7 +186,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<ComplianceItem>> GetComplianceItemAsync(string complianceItemIdHash, CancellationToken cancellationToken = default) => public async Task<Result<ComplianceItem>> GetComplianceItemAsync(string complianceItemIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<ComplianceItem>>>)(async () => await Result.Try((Func<Task<Result<ComplianceItem>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetComplianceItemAsync(complianceItemIdHash, cancellationToken); return await service.GetComplianceItemAsync(complianceItemIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcomplianceitem-{complianceItemIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getcomplianceitem-{complianceItemIdHash}").Value;
@@ -210,7 +210,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<ComplianceItem[]>> GetComplianceItemsAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<ComplianceItem[]>> GetComplianceItemsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<ComplianceItem[]>>>)(async () => await Result.Try((Func<Task<Result<ComplianceItem[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetComplianceItemsAsync(projectIdHash, cancellationToken); return await service.GetComplianceItemsAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getcomplianceitems-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getcomplianceitems-{projectIdHash}").Value;
@@ -234,7 +234,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Issue>> GetIssueAsync(string issueIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Issue>> GetIssueAsync(string issueIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Issue>>>)(async () => await Result.Try((Func<Task<Result<Issue>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetIssueAsync(issueIdHash, cancellationToken); return await service.GetIssueAsync(issueIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getissue-{issueIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getissue-{issueIdHash}").Value;
@@ -258,7 +258,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Issue[]>> GetIssuesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Issue[]>> GetIssuesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Issue[]>>>)(async () => await Result.Try((Func<Task<Result<Issue[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetIssuesAsync(projectIdHash, cancellationToken); return await service.GetIssuesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getissues-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getissues-{projectIdHash}").Value;
@@ -282,7 +282,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Milestone>> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Milestone>>>)(async () => await Result.Try((Func<Task<Result<Milestone>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetMilestoneAsync(milestoneIdHash, cancellationToken); return await service.GetMilestoneAsync(milestoneIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value;
@@ -306,7 +306,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Milestone[]>> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Milestone[]>>>)(async () => await Result.Try((Func<Task<Result<Milestone[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetMilestonesAsync(pagination, cancellationToken); return await service.GetMilestonesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
@@ -330,7 +330,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Outcome>> GetOutcomeAsync(string outcomeIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Outcome>> GetOutcomeAsync(string outcomeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Outcome>>>)(async () => await Result.Try((Func<Task<Result<Outcome>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetOutcomeAsync(outcomeIdHash, cancellationToken); return await service.GetOutcomeAsync(outcomeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getoutcome-{outcomeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getoutcome-{outcomeIdHash}").Value;
@@ -354,7 +354,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Outcome[]>> GetOutcomesAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Outcome[]>> GetOutcomesAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Outcome[]>>>)(async () => await Result.Try((Func<Task<Result<Outcome[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetOutcomesAsync(beneficiaryIdHash, cancellationToken); return await service.GetOutcomesAsync(beneficiaryIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getoutcomes-{beneficiaryIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getoutcomes-{beneficiaryIdHash}").Value;
@@ -378,7 +378,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Outcome[]>> GetProjectOutcomesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Outcome[]>> GetProjectOutcomesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Outcome[]>>>)(async () => await Result.Try((Func<Task<Result<Outcome[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectOutcomesAsync(projectIdHash, cancellationToken); return await service.GetProjectOutcomesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectoutcomes-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectoutcomes-{projectIdHash}").Value;
@@ -402,7 +402,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Programme>> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Programme>>>)(async () => await Result.Try((Func<Task<Result<Programme>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProgrammeAsync(programmeIdHash, cancellationToken); return await service.GetProgrammeAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogramme-{programmeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogramme-{programmeIdHash}").Value;
@@ -426,7 +426,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Project[]>> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Project[]>>>)(async () => await Result.Try((Func<Task<Result<Project[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken); return await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammeprojects-{programmeIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammeprojects-{programmeIdHash}").Value;
@@ -450,7 +450,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Programme[]>> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Programme[]>>>)(async () => await Result.Try((Func<Task<Result<Programme[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProgrammesAsync(pagination, cancellationToken); return await service.GetProgrammesAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprogrammes-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cacheKey = HashService.ToMd5Hash($"getprogrammes-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value;
@@ -474,7 +474,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Project>> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Project>>>)(async () => await Result.Try((Func<Task<Result<Project>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectAsync(projectIdHash, cancellationToken); return await service.GetProjectAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value;
@@ -498,7 +498,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Indicator[]>> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Indicator[]>>>)(async () => await Result.Try((Func<Task<Result<Indicator[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken); return await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value;
@@ -522,7 +522,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Milestone[]>> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Milestone[]>>>)(async () => await Result.Try((Func<Task<Result<Milestone[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken); return await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value;
@@ -546,7 +546,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<Risk[]>> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Risk[]>>>)(async () => await Result.Try((Func<Task<Result<Risk[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectRisksAsync(projectIdHash, cancellationToken); return await service.GetProjectRisksAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value;
@@ -570,7 +570,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => public async Task<Result<Project[]>> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Project[]>>>)(async () => await Result.Try((Func<Task<Result<Project[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetProjectsAsync(pagination, cancellationToken); return await service.GetProjectsAsync(pagination, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value; var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value;
@@ -594,7 +594,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<SiteVisit>> GetSiteVisitAsync(string siteVisitIdHash, CancellationToken cancellationToken = default) => public async Task<Result<SiteVisit>> GetSiteVisitAsync(string siteVisitIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<SiteVisit>>>)(async () => await Result.Try((Func<Task<Result<SiteVisit>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetSiteVisitAsync(siteVisitIdHash, cancellationToken); return await service.GetSiteVisitAsync(siteVisitIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getsitevisit-{siteVisitIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getsitevisit-{siteVisitIdHash}").Value;
@@ -618,7 +618,7 @@ public sealed class ProjectCacheService(ProjectService service, IDistributedCach
public async Task<Result<SiteVisit[]>> GetSiteVisitsAsync(string projectIdHash, CancellationToken cancellationToken = default) => public async Task<Result<SiteVisit[]>> GetSiteVisitsAsync(string projectIdHash, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<SiteVisit[]>>>)(async () => await Result.Try((Func<Task<Result<SiteVisit[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetSiteVisitsAsync(projectIdHash, cancellationToken); return await service.GetSiteVisitsAsync(projectIdHash, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getsitevisits-{projectIdHash}").Value; var cacheKey = HashService.ToMd5Hash($"getsitevisits-{projectIdHash}").Value;
@@ -29,7 +29,7 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async Task<Result<Claim[]>> GetRoleClaimsAsync(Guid roleId, Guid userId, CancellationToken cancellationToken = default) => public async Task<Result<Claim[]>> GetRoleClaimsAsync(Guid roleId, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Claim[]>>>)(async () => await Result.Try((Func<Task<Result<Claim[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetRoleClaimsAsync(roleId, userId, cancellationToken); return await service.GetRoleClaimsAsync(roleId, userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getsystemroles-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getsystemroles-{userId}").Value;
@@ -54,7 +54,7 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async Task<Result<Role[]>> GetSystemRolesAsync(Guid userId, CancellationToken cancellationToken = default) => public async Task<Result<Role[]>> GetSystemRolesAsync(Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Role[]>>>)(async () => await Result.Try((Func<Task<Result<Role[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetSystemRolesAsync(userId, cancellationToken); return await service.GetSystemRolesAsync(userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getsystemroles-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getsystemroles-{userId}").Value;
@@ -79,7 +79,7 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async Task<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken) => public async Task<Result<User>> GetUserAsync(Guid userId, CancellationToken cancellationToken) =>
await Result.Try((Func<Task<Result<User>>>)(async () => await Result.Try((Func<Task<Result<User>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetUserAsync(userId, cancellationToken); return await service.GetUserAsync(userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getuser-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getuser-{userId}").Value;
@@ -103,7 +103,7 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async Task<Result<Claim[]>> GetUserClaimsAsync(Guid targetUserId, Guid userId, CancellationToken cancellationToken = default) => public async Task<Result<Claim[]>> GetUserClaimsAsync(Guid targetUserId, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Claim[]>>>)(async () => await Result.Try((Func<Task<Result<Claim[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetUserClaimsAsync(targetUserId, userId, cancellationToken); return await service.GetUserClaimsAsync(targetUserId, userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getuserclaims-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getuserclaims-{userId}").Value;
@@ -128,7 +128,7 @@ public sealed class UserCacheService(UserService service, IDistributedCache cach
public async Task<Result<Role[]>> GetUserRolesAsync(Guid targetUserId, Guid userId, CancellationToken cancellationToken = default) => public async Task<Result<Role[]>> GetUserRolesAsync(Guid targetUserId, Guid userId, CancellationToken cancellationToken = default) =>
await Result.Try((Func<Task<Result<Role[]>>>)(async () => await Result.Try((Func<Task<Result<Role[]>>>)(async () =>
{ {
if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) if (!await featureManager.IsEnabledAsync(FeatureServiceCaching))
return await service.GetUserRolesAsync(targetUserId, userId, cancellationToken); return await service.GetUserRolesAsync(targetUserId, userId, cancellationToken);
var cacheKey = HashService.ToMd5Hash($"getuserroles-{userId}").Value; var cacheKey = HashService.ToMd5Hash($"getuserroles-{userId}").Value;
@@ -0,0 +1,3 @@
namespace PostFundManagement.Domain.Abstractions;
public interface IDomain;
@@ -9,6 +9,4 @@ public sealed class SmtpSettings
public string? Host { get; set; } public string? Host { get; set; }
public bool UseSsl { get; set; } public bool UseSsl { get; set; }
public string? ProcessorJobCron { get; set; }
} }
@@ -2,8 +2,6 @@ namespace PostFundManagement.Domain.Extensions;
public static class Constants public static class Constants
{ {
public const string ServiceCachingFeature = "EnableServiceCaching";
public const string SkorubaCredentialClient = nameof(SkorubaCredentialClient); public const string SkorubaCredentialClient = nameof(SkorubaCredentialClient);
public const string SkorubaHttpClient = nameof(SkorubaHttpClient); public const string SkorubaHttpClient = nameof(SkorubaHttpClient);
public const string MainScope = "ApiScope"; public const string MainScope = "ApiScope";
@@ -28,4 +26,10 @@ public static class Constants
public const int TextLength = 1024; public const int TextLength = 1024;
public const int MediumTextLength = 2048; public const int MediumTextLength = 2048;
public const int LargeTextLength = 1_048_576; // 1 MB — accommodates branded HTML emails with embedded logo public const int LargeTextLength = 1_048_576; // 1 MB — accommodates branded HTML emails with embedded logo
public const string FeatureEmailProcessor = "EmailProcessorJobEnabled";
public const string FeatureLateProjectReminder = "LateProjectReminderEnabled";
public const string FeatureServiceCaching = "ServiceCaching";
public static Guid SystemUser { get; } = new(0x6059f1e4, 0x6a41, 0x4447, 0xa5, 0x46, 0x86, 0xec, 0xe5, 0x10, 0x20, 0x4) /* 6059f1e4-6a41-4447-a546-86ece5102004 */;
} }
@@ -1,5 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<None Remove="Templates\lateprojectsmilestones.html" />
<None Remove="Templates\noncompliantprojects.html" />
<EmbeddedResource Include="Templates\lateprojectsmilestones.html" />
<EmbeddedResource Include="Templates\noncompliantprojects.html" />
</ItemGroup>
<!-- Transformation --> <!-- Transformation -->
<ItemGroup> <ItemGroup>
<PackageReference Include="Humanizer" /> <PackageReference Include="Humanizer" />
+14 -4
View File
@@ -1,21 +1,31 @@
using PostFundManagement.Application.Events;
using PostFundManagement.Domain.Abstractions; using PostFundManagement.Domain.Abstractions;
using PostFundManagement.Domain.Configuration.Email;
namespace PostFundManagement.Jobs; namespace PostFundManagement.Jobs;
public class JobsWorker(IJobOrchestrator jobOrchestrator, IFeatureManager featureManager, public class JobsWorker(IJobOrchestrator jobOrchestrator, IFeatureManager featureManager,
ILogger<JobsWorker> logger) : BackgroundService ILogger<JobsWorker> logger, IOptions<SmtpSettings> emailOptions) : BackgroundService
{ {
readonly SmtpSettings emailSettings = emailOptions.Value;
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
if (!await featureManager.IsEnabledAsync(nameof(JobsWorker))) if (!await featureManager.IsEnabledAsync(nameof(JobsWorker)))
{ {
logger.LogInformation("JobsWorker is disabled."); logger.LogInformation("Recurring job automatic registration disabled.");
return; return;
} }
// TODO: scheduler reccuring jobs if (await featureManager.IsEnabledAsync(FeatureEmailProcessor))
await jobOrchestrator.ScheduleAsync(ProcessEmailEvent.Create(), "0 */5 * * * ?", stoppingToken);
logger.LogInformation("JobsWorker is stopping."); if (await featureManager.IsEnabledAsync(FeatureLateProjectReminder))
await jobOrchestrator.ScheduleAsync(LateProjectEvent.Create(), "", stoppingToken);
// TODO: Add job to check for non-compliant projects once a week
logger.LogInformation("Recurring jobs have been registered or updated.");
} }
} }
@@ -1,8 +0,0 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
+1 -1
View File
@@ -2,6 +2,7 @@
"FeatureManagement": { "FeatureManagement": {
"JobsWorker": true, "JobsWorker": true,
"EmailProcessorJobEnabled": true, "EmailProcessorJobEnabled": true,
"LateProjectReminderEnabled": true,
"ServiceCaching": false "ServiceCaching": false
}, },
"GeneralS3Settings": { "GeneralS3Settings": {
@@ -28,7 +29,6 @@
} }
}, },
"Email": { "Email": {
"ProcessorJobCron": "0 */5 * * * ?",
"SmtpServer": "smtp.example.com", "SmtpServer": "smtp.example.com",
"SmtpPort": 587, "SmtpPort": 587,
"SenderEmail": "noreply@example.com", "SenderEmail": "noreply@example.com",
+1 -1
View File
@@ -11,6 +11,7 @@ services:
- FeatureManagement__JobsWorker=${FEATURE_JOBS_WORKER} - FeatureManagement__JobsWorker=${FEATURE_JOBS_WORKER}
- FeatureManagement__EmailProcessorJobEnabled=${FEATURE_EMAIL_PROCESSOR_JOB_ENABLED} - FeatureManagement__EmailProcessorJobEnabled=${FEATURE_EMAIL_PROCESSOR_JOB_ENABLED}
- FeatureManagement__ServiceCaching=${FEATURE_SERVICE_CACHING} - FeatureManagement__ServiceCaching=${FEATURE_SERVICE_CACHING}
- FeatureManagement__LateProjectReminderEnabled=${FEATURE_LATE_PROJECT_REMINDER}
# Header forwarding overrides # Header forwarding overrides
- DOTNET_ENVIRONMENT=${ENVIRONMENT:-Development} - DOTNET_ENVIRONMENT=${ENVIRONMENT:-Development}
@@ -48,7 +49,6 @@ services:
- Monitoring__ApiKey=${MONITORING_API_KEY:-} - Monitoring__ApiKey=${MONITORING_API_KEY:-}
# Email Processor Overrides # Email Processor Overrides
- Email__ProcessorJobCron=${EMAIL_PROCESSOR_CRON:-0 */5 * * * ?}
- Email__Credentials__Password=${EMAIL_CREDENTIALS_PASSWORD:-} - Email__Credentials__Password=${EMAIL_CREDENTIALS_PASSWORD:-}
- Email__Credentials__Username=${EMAIL_CREDENTIALS_USERNAME:-} - Email__Credentials__Username=${EMAIL_CREDENTIALS_USERNAME:-}
- Email__SmtpServer=${EMAIL_SMTP_SERVER:-} - Email__SmtpServer=${EMAIL_SMTP_SERVER:-}