So I’m attempting to use reactives to recompose chunked messages identified by ID and am having a problem terminating the final observable. I have a Message class which consists of Id, Total Size, Payload, Chunk Number and Type and have the following client-side code:
I need to calculate the number of messages to Take at runtime
(from messages in
(from messageArgs in Receive select Serializer.Deserialize<Message>(new MemoryStream(Encoding.UTF8.GetBytes(messageArgs.Message))))
group messages by messages.Id into grouped select grouped)
.Subscribe(g =>
{
var cache = new List<Message>();
g.TakeWhile((int) Math.Ceiling(MaxPayload/g.First().Size) < cache.Count)
.Subscribe(cache.Add,
_ => { /* Rebuild Message Parts From Cache */ });
});
First I create a grouped observable filtering messages by their unique ID and then I am trying to cache all messages in each group until I have collected them all, then I sort them and put them together. The above seems to block on g.First().
I need a way to calculate the number to take from the first (or any) of the messages that come through however am having difficulty doing so. Any help?
Firstis a blocking operator (how else can it returnTand notIObservable<T>?)I think using
Scan(which builds an aggregate over time) could be what you need. UsingScan, you can hide the “state” of your message re-construction in a “builder” object.MessageBuilder.IsCompletereturns true when all the size of messages it has received reachesMaxPayload(or whatever your requirements are).MessageBuilder.Build()then returns the reconstructed message.I’ve also moved your “message building” code into a
SelectMany, which keeps the built messages within the monad.(Apologies for reformatting the code into extension methods, I find it difficult to read/write mixed LINQ syntax)