using Dapper; using GmRelay.Shared.Domain; using Npgsql; namespace GmRelay.Bot.Infrastructure.Scheduling; public interface ISessionTriggerStore { Task> GetSessionsNeedingConfirmationAsync(DateTimeOffset now, CancellationToken ct); Task> GetSessionsNeedingOneHourReminderAsync(DateTimeOffset now, CancellationToken ct); Task> GetSessionsNeedingJoinLinkAsync(DateTimeOffset now, CancellationToken ct); } public sealed class DbSessionTriggerStore(NpgsqlDataSource dataSource) : ISessionTriggerStore { private static readonly TimeSpan ConfirmationLeadTime = TimeSpan.FromHours(24); private static readonly TimeSpan OneHourReminderLeadTime = TimeSpan.FromHours(1); private static readonly TimeSpan JoinLinkLeadTime = TimeSpan.FromMinutes(5); public async Task> GetSessionsNeedingConfirmationAsync(DateTimeOffset now, CancellationToken ct) { await using var connection = await dataSource.OpenConnectionAsync(ct); var results = await connection.QueryAsync( """ SELECT id FROM sessions WHERE status = @Planned AND scheduled_at - @LeadTime <= @Now AND confirmation_sent_at IS NULL """, new { Planned = SessionStatus.Planned, LeadTime = ConfirmationLeadTime, Now = now.UtcDateTime }); return results.ToList(); } public async Task> GetSessionsNeedingOneHourReminderAsync(DateTimeOffset now, CancellationToken ct) { await using var connection = await dataSource.OpenConnectionAsync(ct); var results = await connection.QueryAsync( """ SELECT id FROM sessions WHERE status IN (@Confirmed, @ConfirmationSent) AND scheduled_at - @LeadTime <= @Now AND one_hour_reminder_processed_at IS NULL """, new { Confirmed = SessionStatus.Confirmed, ConfirmationSent = SessionStatus.ConfirmationSent, LeadTime = OneHourReminderLeadTime, Now = now.UtcDateTime }); return results.ToList(); } public async Task> GetSessionsNeedingJoinLinkAsync(DateTimeOffset now, CancellationToken ct) { await using var connection = await dataSource.OpenConnectionAsync(ct); var results = await connection.QueryAsync( """ SELECT id FROM sessions WHERE status = @Confirmed AND scheduled_at - @LeadTime <= @Now AND link_message_id IS NULL """, new { Confirmed = SessionStatus.Confirmed, LeadTime = JoinLinkLeadTime, Now = now.UtcDateTime }); return results.ToList(); } }