Add caching to month summary results

This commit is contained in:
2023-05-18 11:49:35 +02:00
parent d6fbf33c7c
commit 71b6fe37a0
4 changed files with 75 additions and 37 deletions

View File

@@ -0,0 +1,9 @@
namespace Solar.Api.Constants;
internal static class CacheKeys
{
public static string GetMonthSummaryCacheKey(string source, int year, int month)
{
return $"month-summary-{source}-{year}-{month}";
}
}

View File

@@ -1,8 +1,8 @@
using System.Net.Mime;
using Microsoft.AspNetCore.Mvc;
using Solar.Api.Models;
using Solar.Api.Services;
using Swashbuckle.AspNetCore.Annotations;
using System.Net.Mime;
namespace Solar.Api.Controllers;

View File

@@ -1,9 +1,9 @@
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
using Microsoft.OpenApi.Models;
using Solar.Api.Converters;
using Solar.Api.Services;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Text.Json;
namespace Solar.Api;
@@ -15,6 +15,7 @@ public partial class Program
// Services
builder.Services.AddScoped<SolarService>();
builder.Services.AddMemoryCache();
// Database
builder.Services.AddDbContext<DatabaseContext>(options =>

View File

@@ -1,4 +1,6 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Memory;
using Solar.Api.Constants;
using Solar.Api.Entities;
using Solar.Api.Models;
@@ -7,13 +9,16 @@ namespace Solar.Api.Services;
public class SolarService
{
private readonly DatabaseContext databaseContext;
private readonly IMemoryCache memoryCache;
private readonly ILogger<SolarService> logger;
public SolarService(
DatabaseContext databaseContext,
IMemoryCache memoryCache,
ILogger<SolarService> logger)
{
this.databaseContext = databaseContext;
this.memoryCache = memoryCache;
this.logger = logger;
}
@@ -48,6 +53,20 @@ public class SolarService
.ToArray());
}
private static void NormalizeEnvoyLogs(EnvoyLog[] entities)
{
if (entities.Length < 1)
{
return;
}
var baseValue = entities[0].TotalWatts;
foreach (var entity in entities)
{
entity.TotalWatts -= baseValue;
}
}
public async Task<DaysResponse> GetDaySummaries(DateOnly start, DateOnly stop)
{
var zeverRecords = await databaseContext
@@ -73,30 +92,6 @@ public class SolarService
return new DaysResponse(logs.ToArray());
}
public async Task<MonthSummariesResponse> GetMonthSummaries(int fromYear, int fromMonth, int toYear, int toMonth)
{
var results = new List<MonthLog>();
var current = (Year: fromYear, Month: fromMonth);
do
{
var zeverResult = (int)await databaseContext.ZeverSummaries
.Where(zs => zs.Date.Year == current.Year && zs.Date.Month == current.Month)
.SumAsync(zs => zs.TotalWatts);
var envoyYear = await GetEnvoyMonthTotalWatts(current.Year, current.Month);
results.Add(new MonthLog(current.Year, current.Month, zeverResult, envoyYear));
if (current.Month == 12)
{
current = (current.Year + 1, 1);
}
else
{
current = (current.Year, current.Month + 1);
}
} while (current.Year < toYear || current.Month < toMonth);
return new MonthSummariesResponse(results.ToArray());
}
private async Task<int> GetEnvoyDayTotalWatts(DateOnly date)
{
var min = await databaseContext.EnvoyLogs
@@ -116,6 +111,35 @@ public class SolarService
return (int)(max.TotalWatts - min.TotalWatts);
}
public async Task<MonthSummariesResponse> GetMonthSummaries(int fromYear, int fromMonth, int toYear, int toMonth)
{
var results = new List<MonthLog>();
var current = (Year: fromYear, Month: fromMonth);
do
{
var zeverResult = await GetOrAddToCache("zever", current.Year, current.Month, GetZeverMonthTotalWatts);
var envoyYear = await GetOrAddToCache("envoy", current.Year, current.Month, GetEnvoyMonthTotalWatts);
results.Add(new MonthLog(current.Year, current.Month, zeverResult, envoyYear));
if (current.Month == 12)
{
current = (current.Year + 1, 1);
}
else
{
current = (current.Year, current.Month + 1);
}
} while (current.Year < toYear || current.Month < toMonth);
return new MonthSummariesResponse(results.ToArray());
}
private async Task<int> GetZeverMonthTotalWatts(int year, int month)
{
return (int)await databaseContext.ZeverSummaries
.Where(zs => zs.Date.Year == year && zs.Date.Month == month)
.SumAsync(zs => zs.TotalWatts);
}
private async Task<int> GetEnvoyMonthTotalWatts(int year, int month)
{
var min = await databaseContext.EnvoyLogs
@@ -135,17 +159,21 @@ public class SolarService
return (int)(max.TotalWatts - min.TotalWatts);
}
private static void NormalizeEnvoyLogs(EnvoyLog[] entities)
private async Task<int> GetOrAddToCache(
string source,
int year,
int month,
Func<int, int, Task<int>> fetchMethod)
{
if (entities.Length < 1)
{
return;
}
var baseValue = entities[0].TotalWatts;
foreach (var entity in entities)
{
entity.TotalWatts -= baseValue;
}
return await memoryCache.GetOrCreateAsync(
CacheKeys.GetMonthSummaryCacheKey(source, year, month),
async (cacheEntry) =>
{
if (DateTime.Today.Month == month && DateTime.Today.Year == year)
{
cacheEntry.SlidingExpiration = TimeSpan.FromHours(12);
}
return await fetchMethod(year, month);
});
}
}