feat(grpc): event-on-session seam for the reuse spike (SendEvent[+ReadEvents])

Extract SendEventOnSession (and best-effort RunEventQueryOnSession) so the B0b spike
can run multiple event ops on one already-opened v8 Event session. RegisterCmEventTag
made independently callable. Behaviour-preserving (pending.md A1 broadening, Stage B0).

Claude-Session: https://claude.ai/code/session_012SDSQ3AcaXqPcBtDESBRii
This commit is contained in:
Joseph Doherty
2026-06-25 10:39:40 -04:00
parent 81aff03748
commit dc4141e718
3 changed files with 90 additions and 3 deletions
@@ -0,0 +1,50 @@
using System.Reflection;
using AVEVA.Historian.Client.Grpc;
using Xunit;
namespace AVEVA.Historian.Client.Tests;
/// <summary>
/// Reflection guard for the event-on-session seams the B0b reuse spike drives (pending.md A1
/// broadening, Stage B0). Mirrors <see cref="TagClientOnSessionSeamTests"/>: the seam runs ONLY the
/// op against an externally-supplied (connection, session), so the spike can run MULTIPLE event ops
/// on one already-opened + registered v8 Event session to measure reuse.
/// </summary>
public class EventOnSessionSeamTests
{
private static MethodInfo RequireMethod(Type owner, string name)
{
MethodInfo? m = owner.GetMethod(
name, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static);
Assert.NotNull(m);
return m!;
}
[Fact]
public void SendEventOnSession_ExposesSeam_WithConnectionAndSessionFirst()
{
MethodInfo m = RequireMethod(typeof(HistorianGrpcEventWriteOrchestrator), "SendEventOnSession");
ParameterInfo[] ps = m.GetParameters();
Assert.Equal("HistorianGrpcConnection", ps[0].ParameterType.Name);
Assert.Equal("Session", ps[1].ParameterType.Name);
}
[Fact]
public void OpenAndRegisterEventSession_ExposesRegisterOnceSeam()
{
// The spike registers CM_EVENT ONCE via this helper, then issues many SendEventOnSession ops.
MethodInfo m = RequireMethod(typeof(HistorianGrpcEventWriteOrchestrator), "OpenAndRegisterEventSession");
ParameterInfo[] ps = m.GetParameters();
Assert.Equal("HistorianGrpcConnection", ps[0].ParameterType.Name);
Assert.Equal("Session", m.ReturnType.Name);
}
[Fact]
public void RunEventQueryOnSession_ExposesSeam_WithConnectionAndSessionFirst()
{
MethodInfo m = RequireMethod(typeof(HistorianGrpcEventOrchestrator), "RunEventQueryOnSession");
ParameterInfo[] ps = m.GetParameters();
Assert.Equal("HistorianGrpcConnection", ps[0].ParameterType.Name);
Assert.Equal("Session", ps[1].ParameterType.Name);
}
}