feat: HistorianEventSession primitive + OpenEventSessionAsync (v8 Event reuse)
Reusable v8 Event session wrapping the B0a seams (OpenAndRegisterEventSession once + SendEventOnSession per op) with a GetSystemParameter keepalive; idempotent dispose. Mirrors HistorianSession (v6 sibling). pending.md A1 broadening, Stage B1. Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
@@ -382,6 +382,38 @@ public sealed class HistorianClient : IAsyncDisposable
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Opens a reusable v8 EVENT session (ECDH + RegisterCmEventTag ONCE) over the 2023 R2 gRPC
|
||||
/// transport. The caller owns the session and must dispose it. Reusing the session across sends
|
||||
/// amortizes the ECDH+register cost (~10-16×, spike-proven); the server idle-expires it in ~25s,
|
||||
/// so keep it warm (HistorianEventSession.PingAsync) or re-open. For SendEvent amortization only —
|
||||
/// event reads are gated (C2) and not exposed here. RemoteGrpc only.
|
||||
/// </summary>
|
||||
public async Task<HistorianEventSession> OpenEventSessionAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (_options.Transport != HistorianTransport.RemoteGrpc)
|
||||
{
|
||||
throw new ProtocolEvidenceMissingException(
|
||||
"HistorianEventSession is only supported over the 2023 R2 RemoteGrpc transport.");
|
||||
}
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
Grpc.HistorianGrpcConnection connection = Grpc.HistorianGrpcChannelFactory.Create(_options);
|
||||
try
|
||||
{
|
||||
var orch = new Grpc.HistorianGrpcEventWriteOrchestrator(_options);
|
||||
Grpc.HistorianGrpcHandshake.Session session = orch.OpenAndRegisterEventSession(connection, cancellationToken);
|
||||
return new HistorianEventSession(connection, session, _options);
|
||||
}
|
||||
catch
|
||||
{
|
||||
connection.Dispose(); // don't leak the channel if the handshake fails
|
||||
throw;
|
||||
}
|
||||
}, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public ValueTask DisposeAsync()
|
||||
{
|
||||
return ValueTask.CompletedTask;
|
||||
|
||||
Reference in New Issue
Block a user