using PostFundManagement.Application.Abstractions.Services; using PostFundManagement.Application.Extensions; using PostFundManagement.Application.Services.Shared; using PostFundManagement.Domain; using PostFundManagement.Domain.Models; namespace PostFundManagement.Application.Services.Projects; public sealed class ProjectCacheService(ProjectService service, IDistributedCache cache, IFeatureManager featureManager) : ServiceCacheBase, IProjectService { public async Task CreateActivityAsync(CreateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateActivityAsync(request, userId, cancellationToken); public async Task UpdateActivityAsync(UpdateActivityRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateActivityAsync(request, userId, cancellationToken); public async Task CreateBeneficiaryAsync(CreateBeneficiaryRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateBeneficiaryAsync(request, userId, cancellationToken); public async Task CreateChangeRequestAsync(CreateChangeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateChangeRequestAsync(request, userId, cancellationToken); public async Task CreateComplianceItemAsync(CreateComplianceItemRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateComplianceItemAsync(request, userId, cancellationToken); public async Task CreateIssueAsync(CreateIssueRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateIssueAsync(request, userId, cancellationToken); public async Task CreateOutcomeAsync(CreateOutcomeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateOutcomeAsync(request, userId, cancellationToken); public async Task CreateProgrammeAsync(CreateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateProgrammeAsync(request, userId, cancellationToken); public async Task CreateProjectAsync(CreateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateProjectAsync(request, userId, cancellationToken); public async Task CreateSiteVisitAsync(CreateSiteVisitRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateSiteVisitAsync(request, userId, cancellationToken); public async Task> GetActivitiesAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetActivitiesAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getactivities-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetActivitiesAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetActivityAsync(string activityIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetActivityAsync(activityIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getactivity-{activityIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetActivityAsync(activityIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetBeneficiariesAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetBeneficiariesAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getbeneficiaries-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetBeneficiariesAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetBeneficiaryAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetBeneficiaryAsync(beneficiaryIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getbeneficiary-{beneficiaryIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetBeneficiaryAsync(beneficiaryIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetChangeRequestAsync(string changeRequestIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetChangeRequestAsync(changeRequestIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getchangerequest-{changeRequestIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetChangeRequestAsync(changeRequestIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetChangeRequestsAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetChangeRequestsAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getchangerequests-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetChangeRequestsAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetComplianceItemAsync(string complianceItemIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetComplianceItemAsync(complianceItemIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getcomplianceitem-{complianceItemIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetComplianceItemAsync(complianceItemIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetComplianceItemsAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetComplianceItemsAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getcomplianceitems-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetComplianceItemsAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetIssueAsync(string issueIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetIssueAsync(issueIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getissue-{issueIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetIssueAsync(issueIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetIssuesAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetIssuesAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getissues-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetIssuesAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetMilestoneAsync(string milestoneIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetMilestoneAsync(milestoneIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getmilestone-{milestoneIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetMilestoneAsync(milestoneIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetMilestonesAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetMilestonesAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getmilestones-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetMilestonesAsync(pagination, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetOutcomeAsync(string outcomeIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetOutcomeAsync(outcomeIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getoutcome-{outcomeIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetOutcomeAsync(outcomeIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetOutcomesAsync(string beneficiaryIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetOutcomesAsync(beneficiaryIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getoutcomes-{beneficiaryIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetOutcomesAsync(beneficiaryIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProgrammeAsync(string programmeIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProgrammeAsync(programmeIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprogramme-{programmeIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProgrammeAsync(programmeIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached!.FromJson()); })); public async Task> GetProgrammeProjectsAsync(string programmeIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprogrammeprojects-{programmeIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProgrammeProjectsAsync(programmeIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProgrammesAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProgrammesAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprogrammes-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProgrammesAsync(pagination, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProjectAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProjectAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getproject-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProjectAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProjectIndicatorsAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprojectindicators-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProjectIndicatorsAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProjectMilestonesAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprojectmilestones-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProjectMilestonesAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProjectRisksAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProjectRisksAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprojectrisks-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProjectRisksAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetProjectsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetProjectsAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getprojects-{pagination.Index}-{pagination.Page}-{pagination.PageSize}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetProjectsAsync(pagination, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetSiteVisitAsync(string siteVisitIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetSiteVisitAsync(siteVisitIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getsitevisit-{siteVisitIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetSiteVisitAsync(siteVisitIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task> GetSiteVisitsAsync(string projectIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetSiteVisitsAsync(projectIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getsitevisits-{projectIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetSiteVisitsAsync(projectIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value.ToJson(), cacheOptions, cancellationToken); return result.Value; } return Result.Ok(cached.FromJson()); })); public async Task UpdateBeneficiaryAsync(UpdateBeneficiaryRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateBeneficiaryAsync(request, userId, cancellationToken); public async Task UpdateChangeRequestAsync(UpdateChangeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateChangeRequestAsync(request, userId, cancellationToken); public async Task UpdateComplianceItemAsync(UpdateComplianceItemRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateComplianceItemAsync(request, userId, cancellationToken); public async Task UpdateIssueAsync(UpdateIssueRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateIssueAsync(request, userId, cancellationToken); public async Task UpdateMilestoneAsync(UpdateMilestoneRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateMilestoneAsync(request, userId, cancellationToken); public async Task UpdateOutcomeAsync(UpdateOutcomeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateOutcomeAsync(request, userId, cancellationToken); public async Task UpdateProgrammeAsync(UpdateProgrammeRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateProgrammeAsync(request, userId, cancellationToken); public async Task UpdateProjectAsync(UpdateProjectRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateProjectAsync(request, userId, cancellationToken); public async Task UpdateProjectStatusAsync(UpdateProjectStatusRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateProjectStatusAsync(request, userId, cancellationToken); public async Task UpdateSiteVisitAsync(UpdateSiteVisitRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateSiteVisitAsync(request, userId, cancellationToken); }