Files
GmRelayBot/src/GmRelay.Shared/Features/Sessions/CreateSession/ScheduleMessageUpdateLock.cs
T
Toutsu 39132be4e8
PR Checks / test-and-build (pull_request) Successful in 6m6s
feat(discord): enable session join leave buttons
Move neutral join/leave handlers into GmRelay.Shared so Telegram and Discord share capacity, waitlist, duplicate-click, and schedule-update behavior.

Add Discord component routing for join_session and leave_session buttons with deferred ephemeral replies and serialized schedule message updates.

Bump version to 2.5.0 and update Discord docs.

Refs #29
2026-05-19 14:13:48 +03:00

40 lines
1.3 KiB
C#

using System.Collections.Concurrent;
using GmRelay.Shared.Platform;
namespace GmRelay.Shared.Features.Sessions.CreateSession;
public interface IScheduleMessageUpdateLock
{
ValueTask<IAsyncDisposable> AcquireAsync(PlatformMessageRef scheduleMessage, CancellationToken ct);
}
public sealed class ScheduleMessageUpdateLock : IScheduleMessageUpdateLock
{
private readonly ConcurrentDictionary<string, SemaphoreSlim> locks = new(StringComparer.Ordinal);
public async ValueTask<IAsyncDisposable> AcquireAsync(PlatformMessageRef scheduleMessage, CancellationToken ct)
{
var key = CreateKey(scheduleMessage);
var semaphore = locks.GetOrAdd(key, _ => new SemaphoreSlim(1, 1));
await semaphore.WaitAsync(ct);
return new Releaser(semaphore);
}
private static string CreateKey(PlatformMessageRef scheduleMessage) =>
string.Join(
'\u001F',
scheduleMessage.Platform.ToString(),
scheduleMessage.ExternalGroupId,
scheduleMessage.ExternalThreadId ?? string.Empty,
scheduleMessage.ExternalMessageId);
private sealed class Releaser(SemaphoreSlim semaphore) : IAsyncDisposable
{
public ValueTask DisposeAsync()
{
semaphore.Release();
return ValueTask.CompletedTask;
}
}
}