Files
Rendezvous/src/FinalFactory.Rendezvous.Client/RendezvousPublisherClient.cs
T
KyuubiYoru 94aba8a3bb
quality-gate / quality (push) Successful in 59s
feat(client): standardize connection outcomes (#13)
2026-07-16 10:18:41 +02:00

155 lines
5.6 KiB
C#

using FinalFactory.Rendezvous.Contracts;
namespace FinalFactory.Rendezvous.Client;
public sealed class RendezvousPublisherClient : IRendezvousPublisherClient
{
private readonly RendezvousHttpTransport _transport;
private readonly IRendezvousDelay _delay;
public RendezvousPublisherClient(
HttpClient httpClient,
RendezvousClientOptions? options = null,
IRendezvousDelay? delay = null)
{
_delay = delay ?? new SystemRendezvousDelay();
_transport = new(httpClient, options, _delay);
}
public async Task<RendezvousClientResult<PublishedSession>> RegisterAsync(
RegisterSessionRequest request,
string publisherCredential,
CancellationToken cancellationToken = default)
{
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
RegisterSessionRequest body = CopyRegistration(request);
RendezvousClientResult<RegisterSessionResponse> result = await _transport.SendSafeAsync<RegisterSessionResponse>(
() => RendezvousHttpTransport.JsonRequest(HttpMethod.Post, "v1/sessions", body, publisherCredential),
cancellationToken).ConfigureAwait(false);
return result.IsSuccess && result.Value is not null
? RendezvousClientResult.Success(new PublishedSession(result.Value))
: RendezvousClientResult.Failure<PublishedSession>(
result.Error,
result.Message,
result.RetryAfterSeconds);
}
public async Task<RendezvousClientResult<RenewLeaseResponse>> RenewAsync(
PublishedSession session,
string publisherCredential,
CancellationToken cancellationToken = default)
{
if (session is null)
{
throw new ArgumentNullException(nameof(session));
}
RendezvousClientResult<RenewLeaseResponse> result = await _transport.SendSafeAsync<RenewLeaseResponse>(
() => RendezvousHttpTransport.JsonRequest(
HttpMethod.Post,
$"v1/sessions/{session.ListingId}/renew",
new RenewLeaseRequest { LeaseToken = session.LeaseToken },
publisherCredential),
cancellationToken).ConfigureAwait(false);
if (result.IsSuccess && result.Value is not null)
{
session.ExpiresAt = result.Value.ExpiresAt;
session.LeaseRenewAfterSeconds = result.Value.RenewAfterSeconds;
}
return result;
}
public Task<RendezvousClientResult<bool>> UpdateAsync(
PublishedSession session,
UpdateSessionRequest request,
string publisherCredential,
CancellationToken cancellationToken = default)
{
if (session is null)
{
throw new ArgumentNullException(nameof(session));
}
if (request is null)
{
throw new ArgumentNullException(nameof(request));
}
UpdateSessionRequest body = new()
{
ContractVersion = request.ContractVersion,
LeaseToken = session.LeaseToken,
BuildVersion = request.BuildVersion,
DisplayName = request.DisplayName,
Capacity = CopyCapacity(request.Capacity),
Metadata = CopyMetadata(request.Metadata),
DedicatedFallback = RendezvousEndpoint.Copy(request.DedicatedFallback),
};
return _transport.SendSafeAsync<bool>(
() => RendezvousHttpTransport.JsonRequest(
HttpMethod.Put,
$"v1/sessions/{session.ListingId}",
body,
publisherCredential),
cancellationToken);
}
public Task<RendezvousClientResult<bool>> DeregisterAsync(
PublishedSession session,
string publisherCredential,
CancellationToken cancellationToken = default)
{
if (session is null)
{
throw new ArgumentNullException(nameof(session));
}
return _transport.SendSafeAsync<bool>(
() => RendezvousHttpTransport.JsonRequest(
HttpMethod.Delete,
$"v1/sessions/{session.ListingId}",
new DeleteSessionRequest { LeaseToken = session.LeaseToken },
publisherCredential),
cancellationToken);
}
public SessionLeaseMaintainer CreateLeaseMaintainer(
PublishedSession session,
string publisherCredential) => new(
this,
session ?? throw new ArgumentNullException(nameof(session)),
RendezvousHttpTransport.RequireCredential(publisherCredential),
_delay);
private static RegisterSessionRequest CopyRegistration(RegisterSessionRequest request) => new()
{
ContractVersion = request.ContractVersion,
IdempotencyKey = request.IdempotencyKey,
GameId = request.GameId,
EnvironmentId = request.EnvironmentId,
RegionId = request.RegionId,
ProtocolVersion = request.ProtocolVersion,
BuildVersion = request.BuildVersion,
DisplayName = request.DisplayName,
Visibility = request.Visibility,
Capacity = CopyCapacity(request.Capacity),
Metadata = CopyMetadata(request.Metadata),
DedicatedFallback = RendezvousEndpoint.Copy(request.DedicatedFallback),
};
private static SessionCapacity CopyCapacity(SessionCapacity capacity) => new()
{
CurrentPlayers = capacity.CurrentPlayers,
MaximumPlayers = capacity.MaximumPlayers,
};
private static Dictionary<string, string> CopyMetadata(Dictionary<string, string> metadata) =>
new(metadata, StringComparer.Ordinal);
}