110 lines
4.0 KiB
C#
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();
|
|
}
|
|
}
|