Files
GmRelayBot/src/GmRelay.Shared/Infrastructure/Scheduling/ISessionTriggerStore.cs
T
Toutsu 2a707e4825
PR Checks / test-and-build (pull_request) Successful in 7m9s
feat(platform): route scheduler notifications through platform messenger
2026-05-21 12:30:35 +03:00

110 lines
4.0 KiB
C#

using Dapper;
using GmRelay.Shared.Domain;
using Npgsql;
namespace GmRelay.Shared.Infrastructure.Scheduling;
public interface ISessionTriggerStore
{
Task<IReadOnlyList<Guid>> GetSessionsNeedingConfirmationAsync(DateTimeOffset now, CancellationToken ct);
Task<IReadOnlyList<Guid>> GetSessionsNeedingOneHourReminderAsync(DateTimeOffset now, CancellationToken ct);
Task<IReadOnlyList<Guid>> GetSessionsNeedingJoinLinkAsync(DateTimeOffset now, CancellationToken ct);
}
public sealed class DbSessionTriggerStore(
NpgsqlDataSource dataSource,
PlatformSchedulerOptions options) : 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<IReadOnlyList<Guid>> GetSessionsNeedingConfirmationAsync(DateTimeOffset now, CancellationToken ct)
{
await using var connection = await dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<Guid>(
"""
SELECT s.id
FROM sessions s
JOIN game_groups g ON g.id = s.group_id
WHERE g.platform = @Platform
AND s.status = @Planned
AND s.scheduled_at - @LeadTime <= @Now
AND s.confirmation_sent_at IS NULL
""",
new
{
Platform = options.Platform.ToString(),
Planned = SessionStatus.Planned,
LeadTime = ConfirmationLeadTime,
Now = now.UtcDateTime
});
return results.ToList();
}
public async Task<IReadOnlyList<Guid>> GetSessionsNeedingOneHourReminderAsync(DateTimeOffset now, CancellationToken ct)
{
await using var connection = await dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<Guid>(
"""
SELECT s.id
FROM sessions s
JOIN game_groups g ON g.id = s.group_id
WHERE g.platform = @Platform
AND s.status IN (@Confirmed, @ConfirmationSent)
AND s.scheduled_at - @LeadTime <= @Now
AND s.one_hour_reminder_processed_at IS NULL
""",
new
{
Platform = options.Platform.ToString(),
Confirmed = SessionStatus.Confirmed,
ConfirmationSent = SessionStatus.ConfirmationSent,
LeadTime = OneHourReminderLeadTime,
Now = now.UtcDateTime
});
return results.ToList();
}
public async Task<IReadOnlyList<Guid>> GetSessionsNeedingJoinLinkAsync(DateTimeOffset now, CancellationToken ct)
{
await using var connection = await dataSource.OpenConnectionAsync(ct);
var results = await connection.QueryAsync<Guid>(
"""
SELECT s.id
FROM sessions s
JOIN game_groups g ON g.id = s.group_id
WHERE g.platform = @Platform
AND s.status = @Confirmed
AND s.scheduled_at - @LeadTime <= @Now
AND (
(g.platform = 'Telegram' AND s.link_message_id IS NULL)
OR (
g.platform <> 'Telegram'
AND NOT EXISTS (
SELECT 1
FROM platform_messages pm
WHERE pm.session_id = s.id
AND pm.platform = g.platform
AND pm.purpose = 'join_link'
)
)
)
""",
new
{
Platform = options.Platform.ToString(),
Confirmed = SessionStatus.Confirmed,
LeadTime = JoinLinkLeadTime,
Now = now.UtcDateTime
});
return results.ToList();
}
}