I have a feeling that this is going to leave me feeling blonde - I must be missing something simple. I have a set of GRPC integration tests on a ServiceStack Test host which are all passing, and a set of integration tests using the ServerEvents Feature which are working as well (using the standard ServiceStack ServerEvents client) I am now trying to build out some integration tests which use the grpc streaming features, which looks like this :
It’s because you’re not using a selector in your Server Event notifications, you should instead be comparing against the channel since you’re using the channel name, e.g:
I’m sorry @mythz you’re right, if I change the test as you indicated it passes - but the message is still not being received…I only get the onConnect and onJoin commands. If I change the test to the following, a breakpoint at line #46 is never hit :
Not familiar with XUnit but it seems to hinder finding out what’s going on as I can’t see any logs and have to resort to debugging unlike being able to see the Console logs like with NUnit.
If you don’t specify a selector an automatic one is used with the format of cmd.{typeof(Message)} which as you’re sending a string ends up being cmd.String, normally you’d want to send DTOs which your client code is expecting to deserialize but your sending the Message string not the SendMessage DTO your expecting.
So I’d change your server implementation to send the DTO instead:
public object Any(SendMessage request)
{
if (string.IsNullOrWhiteSpace(request.Channel))
{
_serverEvents.NotifyAll(request);
}
else
{
_serverEvents.NotifyChannel(request.Channel, request);
}
return new SendMessageResponse();
}
Then change your client implementation so the message is sent after the client is connected to the SSE Stream, e.g. test passes when changing it to:
Task.Factory.StartNew(async () => {
await Task.Delay(500);
var client = _fixture.CreateGrpcClient();
var postTask = await client.PostAsync(new SendMessage {Message = "Hello", Channel = "send-messages"});
});
var client = _fixture.CreateGrpcClient();
var stream = client.StreamAsync(new StreamServerEvents
{
Channels = new[] {"send-messages"}
});
await foreach (var msg in stream)
{
$"EVENT({msg.Op}) {msg.Selector} [{msg.Channel}]: #{msg.UserId} {msg.DisplayName}".Print();
if (msg.Selector == "cmd." + nameof(SendMessage))
{
var notification = msg.Json.FromJson<SendMessage>();
Assert.Equal("Hello", notification.Message);
break;
}
}
I’d recommend using and switching on explicit selectors (which you can think of as the Route or handler for the message) rather than relying on implicitly generated ones or you can use the cmd.{TypeName} convention as long as you only send DTO Type messages.