Utopia-Canteen-System/Services/DbMealSessionResolver.cs

72 lines
2.4 KiB
C#

using UtopiaCanteenSystem.Models;
namespace UtopiaCanteenSystem.Services;
/// <summary>
/// Resolves current meal session from production (MySQL meal_schedule). Caches schedules per site for 60 seconds.
/// No SQLite; scan validation uses production data only.
/// </summary>
public class DbMealSessionResolver : IMealSessionResolver
{
private readonly IMealScheduleService _mealScheduleService;
private readonly TimeSpan _cacheTtl = TimeSpan.FromSeconds(60);
private readonly Dictionary<string, (List<MealSchedule> Schedules, DateTime ExpiryUtc)> _cache = new(StringComparer.OrdinalIgnoreCase);
private readonly object _cacheLock = new();
public DbMealSessionResolver(IMealScheduleService mealScheduleService)
{
_mealScheduleService = mealScheduleService;
}
/// <inheritdoc />
public MealSession GetCurrentSession(DateTime nowLocal, string siteId)
{
var normalizedSite = (siteId ?? string.Empty).Trim();
if (string.IsNullOrEmpty(normalizedSite))
normalizedSite = "01";
if (normalizedSite.Length == 1 && char.IsDigit(normalizedSite[0]))
normalizedSite = normalizedSite.PadLeft(2, '0');
var schedules = GetSchedulesForSiteCached(normalizedSite);
var t = nowLocal.TimeOfDay;
foreach (var s in schedules)
{
if (!TryParseTime(s.StartTime, out var start) || !TryParseTime(s.EndTime, out var end))
continue;
if (t >= start && t < end)
return (MealSession)s.MealSession;
}
return MealSession.None;
}
private List<MealSchedule> GetSchedulesForSiteCached(string siteId)
{
lock (_cacheLock)
{
if (_cache.TryGetValue(siteId, out var entry) && DateTime.UtcNow < entry.ExpiryUtc)
return entry.Schedules;
}
var list = _mealScheduleService.GetActiveSchedulesForSite(siteId).ToList();
lock (_cacheLock)
{
_cache[siteId] = (list, DateTime.UtcNow.Add(_cacheTtl));
}
return list;
}
private static bool TryParseTime(string value, out TimeSpan time)
{
time = TimeSpan.Zero;
if (string.IsNullOrWhiteSpace(value))
return false;
return TimeSpan.TryParse(value.Trim(), null, out time)
|| TimeSpan.TryParse(value.Trim().Replace(".", ":"), null, out time);
}
}