Add bulk MXAccess subscription commands

This commit is contained in:
Joseph Doherty
2026-04-26 22:29:27 -04:00
parent daff16cfd2
commit 3d11ac3316
31 changed files with 14346 additions and 969 deletions
@@ -416,6 +416,74 @@ public sealed class MxAccessCommandExecutorTests
Assert.Equal(MxAccessAdviceKind.Plain, adviceHandle.AdviceKind);
}
[Fact]
public async Task DispatchAsync_SubscribeBulk_RunsSequentialMxAccessCallsAndReturnsPerItemResults()
{
FakeMxAccessComObject fakeComObject = new(
registerHandle: 60,
addItemHandle: 512);
FakeMxAccessComObjectFactory factory = new(fakeComObject);
using StaRuntime runtime = CreateRuntime();
using MxAccessStaSession session = new(runtime, factory, new NoopEventSink());
await session.StartAsync(workerProcessId: 1234);
MxCommandReply reply = await session.DispatchAsync(CreateSubscribeBulkCommand(
"subscribe-bulk",
60,
["", "Galaxy.Tag.Value"]));
Assert.Equal(ProtocolStatusCode.Ok, reply.ProtocolStatus.Code);
Assert.Equal(MxCommandKind.SubscribeBulk, reply.Kind);
Assert.Collection(
reply.SubscribeBulk.Results,
result =>
{
Assert.False(result.WasSuccessful);
Assert.Equal(string.Empty, result.TagAddress);
Assert.Equal(0, result.ItemHandle);
Assert.Contains("required", result.ErrorMessage, StringComparison.OrdinalIgnoreCase);
},
result =>
{
Assert.True(result.WasSuccessful);
Assert.Equal("Galaxy.Tag.Value", result.TagAddress);
Assert.Equal(512, result.ItemHandle);
});
Assert.Equal(
["AddItem:60:Galaxy.Tag.Value", "Advise:60:512"],
fakeComObject.OperationNames);
Assert.Equal(runtime.StaThreadId, fakeComObject.AddItemThreadId);
Assert.Equal(runtime.StaThreadId, fakeComObject.AdviseThreadId);
}
[Fact]
public async Task DispatchAsync_UnsubscribeBulk_RemovesItemAfterUnAdviseFailure()
{
const int hresult = unchecked((int)0x80070057);
FakeMxAccessComObject fakeComObject = new(
registerHandle: 61,
unAdviseException: new COMException("Invalid item handle.", hresult));
FakeMxAccessComObjectFactory factory = new(fakeComObject);
using StaRuntime runtime = CreateRuntime();
using MxAccessStaSession session = new(runtime, factory, new NoopEventSink());
await session.StartAsync(workerProcessId: 1234);
MxCommandReply reply = await session.DispatchAsync(CreateUnsubscribeBulkCommand(
"unsubscribe-bulk",
61,
[513]));
Assert.Equal(ProtocolStatusCode.Ok, reply.ProtocolStatus.Code);
SubscribeResult result = Assert.Single(reply.UnsubscribeBulk.Results);
Assert.False(result.WasSuccessful);
Assert.Equal(513, result.ItemHandle);
Assert.Equal(string.Empty, result.TagAddress);
Assert.Contains("UnAdvise failed", result.ErrorMessage);
Assert.Equal(
["UnAdvise:61:513", "RemoveItem:61:513"],
fakeComObject.OperationNames);
}
[Fact]
public async Task ShutdownGracefullyAsync_CleansHandlesInAdviceItemServerOrder()
{
@@ -658,6 +726,48 @@ public sealed class MxAccessCommandExecutorTests
});
}
private static StaCommand CreateSubscribeBulkCommand(
string correlationId,
int serverHandle,
IEnumerable<string> tagAddresses)
{
SubscribeBulkCommand command = new()
{
ServerHandle = serverHandle,
};
command.TagAddresses.Add(tagAddresses);
return new StaCommand(
"session-1",
correlationId,
new MxCommand
{
Kind = MxCommandKind.SubscribeBulk,
SubscribeBulk = command,
});
}
private static StaCommand CreateUnsubscribeBulkCommand(
string correlationId,
int serverHandle,
IEnumerable<int> itemHandles)
{
UnsubscribeBulkCommand command = new()
{
ServerHandle = serverHandle,
};
command.ItemHandles.Add(itemHandles);
return new StaCommand(
"session-1",
correlationId,
new MxCommand
{
Kind = MxCommandKind.UnsubscribeBulk,
UnsubscribeBulk = command,
});
}
private static StaCommand CreateAdviseSupervisoryCommand(
string correlationId,
int serverHandle,