Files
chesscubing/ChessCubing.Server/Social/CollaborativeMatchCoordinator.cs

90 lines
2.8 KiB
C#

namespace ChessCubing.Server.Social;
public sealed class CollaborativeMatchCoordinator
{
private readonly object _sync = new();
private readonly Dictionary<string, CollaborativeSessionState> _sessions = new(StringComparer.Ordinal);
public void RegisterSession(PlaySessionResponse session)
{
lock (_sync)
{
_sessions[session.SessionId] = new CollaborativeSessionState(
session.SessionId,
new HashSet<string>(StringComparer.Ordinal)
{
session.WhiteSubject,
session.BlackSubject,
session.InitiatorSubject,
session.RecipientSubject,
},
null,
0);
}
}
public bool CanAccessSession(string sessionId, string subject)
{
lock (_sync)
{
return _sessions.TryGetValue(sessionId, out var session)
&& session.ParticipantSubjects.Contains(subject);
}
}
public CollaborativeMatchStateMessage? GetLatestState(string sessionId, string subject)
{
lock (_sync)
{
if (!_sessions.TryGetValue(sessionId, out var session) ||
!session.ParticipantSubjects.Contains(subject))
{
throw new SocialValidationException("Cette session de partie est introuvable ou n'est pas accessible.");
}
return session.LatestState;
}
}
public CollaborativeMatchStateMessage PublishState(
string sessionId,
string subject,
string? matchJson,
string route)
{
lock (_sync)
{
if (!_sessions.TryGetValue(sessionId, out var session) ||
!session.ParticipantSubjects.Contains(subject))
{
throw new SocialValidationException("Cette session de partie est introuvable ou n'est pas accessible.");
}
var revision = session.Revision + 1;
var message = new CollaborativeMatchStateMessage
{
SessionId = sessionId,
MatchJson = matchJson,
Route = string.IsNullOrWhiteSpace(route) ? "/application.html" : route.Trim(),
SenderSubject = subject,
Revision = revision,
UpdatedUtc = DateTime.UtcNow,
};
_sessions[sessionId] = session with
{
Revision = revision,
LatestState = message,
};
return message;
}
}
private sealed record CollaborativeSessionState(
string SessionId,
HashSet<string> ParticipantSubjects,
CollaborativeMatchStateMessage? LatestState,
long Revision);
}