250 lines
7.3 KiB
C#
250 lines
7.3 KiB
C#
using MxGateway.Contracts.Proto;
|
|
|
|
namespace MxGateway.Client;
|
|
|
|
/// <summary>
|
|
/// Represents one gateway-backed MXAccess session.
|
|
/// </summary>
|
|
public sealed class MxGatewaySession : IAsyncDisposable
|
|
{
|
|
private readonly MxGatewayClient _client;
|
|
private readonly SemaphoreSlim _closeLock = new(1, 1);
|
|
private CloseSessionReply? _closeReply;
|
|
|
|
internal MxGatewaySession(
|
|
MxGatewayClient client,
|
|
OpenSessionReply openSessionReply)
|
|
{
|
|
_client = client ?? throw new ArgumentNullException(nameof(client));
|
|
OpenSessionReply = openSessionReply ?? throw new ArgumentNullException(nameof(openSessionReply));
|
|
}
|
|
|
|
public string SessionId => OpenSessionReply.SessionId;
|
|
|
|
public OpenSessionReply OpenSessionReply { get; }
|
|
|
|
public async Task<CloseSessionReply> CloseAsync(CancellationToken cancellationToken = default)
|
|
{
|
|
if (_closeReply is not null)
|
|
{
|
|
return _closeReply;
|
|
}
|
|
|
|
await _closeLock.WaitAsync(cancellationToken).ConfigureAwait(false);
|
|
try
|
|
{
|
|
if (_closeReply is not null)
|
|
{
|
|
return _closeReply;
|
|
}
|
|
|
|
_closeReply = await _client.CloseSessionRawAsync(
|
|
new CloseSessionRequest { SessionId = SessionId },
|
|
cancellationToken)
|
|
.ConfigureAwait(false);
|
|
return _closeReply;
|
|
}
|
|
finally
|
|
{
|
|
_closeLock.Release();
|
|
}
|
|
}
|
|
|
|
public async Task<int> RegisterAsync(
|
|
string clientName,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
MxCommandReply reply = await RegisterRawAsync(clientName, cancellationToken)
|
|
.ConfigureAwait(false);
|
|
return reply.Register?.ServerHandle ?? reply.ReturnValue.Int32Value;
|
|
}
|
|
|
|
public Task<MxCommandReply> RegisterRawAsync(
|
|
string clientName,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(clientName);
|
|
|
|
return InvokeCommandAsync(
|
|
new MxCommand
|
|
{
|
|
Kind = MxCommandKind.Register,
|
|
Register = new RegisterCommand { ClientName = clientName },
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public async Task<int> AddItemAsync(
|
|
int serverHandle,
|
|
string itemDefinition,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
MxCommandReply reply = await AddItemRawAsync(
|
|
serverHandle,
|
|
itemDefinition,
|
|
cancellationToken)
|
|
.ConfigureAwait(false);
|
|
return reply.AddItem?.ItemHandle ?? reply.ReturnValue.Int32Value;
|
|
}
|
|
|
|
public Task<MxCommandReply> AddItemRawAsync(
|
|
int serverHandle,
|
|
string itemDefinition,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(itemDefinition);
|
|
|
|
return InvokeCommandAsync(
|
|
new MxCommand
|
|
{
|
|
Kind = MxCommandKind.AddItem,
|
|
AddItem = new AddItemCommand
|
|
{
|
|
ServerHandle = serverHandle,
|
|
ItemDefinition = itemDefinition,
|
|
},
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public async Task<int> AddItem2Async(
|
|
int serverHandle,
|
|
string itemDefinition,
|
|
string itemContext,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
MxCommandReply reply = await AddItem2RawAsync(
|
|
serverHandle,
|
|
itemDefinition,
|
|
itemContext,
|
|
cancellationToken)
|
|
.ConfigureAwait(false);
|
|
return reply.AddItem2?.ItemHandle ?? reply.ReturnValue.Int32Value;
|
|
}
|
|
|
|
public Task<MxCommandReply> AddItem2RawAsync(
|
|
int serverHandle,
|
|
string itemDefinition,
|
|
string itemContext,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentException.ThrowIfNullOrWhiteSpace(itemDefinition);
|
|
|
|
return InvokeCommandAsync(
|
|
new MxCommand
|
|
{
|
|
Kind = MxCommandKind.AddItem2,
|
|
AddItem2 = new AddItem2Command
|
|
{
|
|
ServerHandle = serverHandle,
|
|
ItemDefinition = itemDefinition,
|
|
ItemContext = itemContext ?? string.Empty,
|
|
},
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public async Task AdviseAsync(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
await AdviseRawAsync(serverHandle, itemHandle, cancellationToken)
|
|
.ConfigureAwait(false);
|
|
}
|
|
|
|
public Task<MxCommandReply> AdviseRawAsync(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return InvokeCommandAsync(
|
|
new MxCommand
|
|
{
|
|
Kind = MxCommandKind.Advise,
|
|
Advise = new AdviseCommand
|
|
{
|
|
ServerHandle = serverHandle,
|
|
ItemHandle = itemHandle,
|
|
},
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public async Task WriteAsync(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
MxValue value,
|
|
int userId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
await WriteRawAsync(serverHandle, itemHandle, value, userId, cancellationToken)
|
|
.ConfigureAwait(false);
|
|
}
|
|
|
|
public Task<MxCommandReply> WriteRawAsync(
|
|
int serverHandle,
|
|
int itemHandle,
|
|
MxValue value,
|
|
int userId,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(value);
|
|
|
|
return InvokeCommandAsync(
|
|
new MxCommand
|
|
{
|
|
Kind = MxCommandKind.Write,
|
|
Write = new WriteCommand
|
|
{
|
|
ServerHandle = serverHandle,
|
|
ItemHandle = itemHandle,
|
|
Value = value,
|
|
UserId = userId,
|
|
},
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public Task<MxCommandReply> InvokeAsync(
|
|
MxCommandRequest request,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(request);
|
|
return _client.InvokeAsync(request, cancellationToken);
|
|
}
|
|
|
|
public IAsyncEnumerable<MxEvent> StreamEventsAsync(
|
|
ulong afterWorkerSequence = 0,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
return _client.StreamEventsAsync(
|
|
new StreamEventsRequest
|
|
{
|
|
SessionId = SessionId,
|
|
AfterWorkerSequence = afterWorkerSequence,
|
|
},
|
|
cancellationToken);
|
|
}
|
|
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
await CloseAsync().ConfigureAwait(false);
|
|
_closeLock.Dispose();
|
|
}
|
|
|
|
private Task<MxCommandReply> InvokeCommandAsync(
|
|
MxCommand command,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
return _client.InvokeAsync(
|
|
new MxCommandRequest
|
|
{
|
|
SessionId = SessionId,
|
|
ClientCorrelationId = Guid.NewGuid().ToString("N"),
|
|
Command = command,
|
|
},
|
|
cancellationToken);
|
|
}
|
|
}
|