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.Grants; public sealed class GrantsCacheService(GrantsService service, IDistributedCache cache, IFeatureManager featureManager) : ServiceCacheBase, IGrantsService { public async Task CreateAwardAsync(CreateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateAwardAsync(request, userId, cancellationToken); public async Task UpdateAwardAsync(UpdateAwardRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateAwardAsync(request, userId, cancellationToken); public async Task CreateBudgetAsync(CreateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateBudgetAsync(request, userId, cancellationToken); public async Task CreateContractAsync(CreateContractRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.CreateContractAsync(request, userId, cancellationToken); public async Task ExecuteContractAsync(ExecuteContractRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.ExecuteContractAsync(request, userId, cancellationToken); public async Task> GetAwardAsync(string awardIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetAwardAsync(awardIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getaward-{awardIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetAwardAsync(awardIdHash, 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> GetAwardsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetAwardsAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getawards-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetAwardsAsync(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> GetBudgetAsync(string budgetIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetBudgetAsync(budgetIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getbudget-{budgetIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetBudgetAsync(budgetIdHash, 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> GetBudgetsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetBudgetsAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getbudgets-{pagination.Page}-{pagination.PageSize}-{pagination.Index}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetBudgetsAsync(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> GetContractAsync(string contractIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetContractAsync(contractIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getctract-{contractIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetContractAsync(contractIdHash, 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> GetContractsAsync(Pagination pagination, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetContractsAsync(pagination, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getcontracts-{pagination.Index}-{pagination.PageSize}-{pagination.Page}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetContractsAsync(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> GetContractUrlAsync(string contractIdHash, CancellationToken cancellationToken = default) => await Result.Try((Func>>)(async () => { if (!await featureManager.IsEnabledAsync(ServiceCachingFeature)) return await service.GetContractUrlAsync(contractIdHash, cancellationToken); var cacheKey = HashService.ToMd5Hash($"getcontracturl-{contractIdHash}").Value; var cached = await cache.GetStringAsync(cacheKey, cancellationToken); if (string.IsNullOrWhiteSpace(cached)) { var result = await service.GetContractUrlAsync(contractIdHash, cancellationToken); if (result.IsFailed) return result; await cache.SetStringAsync(cacheKey, result.Value, cancellationToken); return result.Value; } return Result.Ok(cached!); })); public async Task UpdateBudgetAsync(UpdateBudgetRequest request, Guid userId, CancellationToken cancellationToken = default) => await service.UpdateBudgetAsync(request, userId, cancellationToken); public async Task UpdateContractAsync(UpdateContractRequest request, CancellationToken cancellationToken = default) => await service.UpdateContractAsync(request, cancellationToken); public async Task UploadContractAsync(string contractIdHash, Guid userId, IFormFile file, CancellationToken cancellationToken = default) => await service.UploadContractAsync(contractIdHash, userId, file, cancellationToken); }