public static TMessageResponse?PublishAndWaitForExclusiveResponse <TMessageRequest, TMessageResponse>(this INetworkBus bus, TMessageRequest message, int timeout = -1) where TMessageRequest : notnull, IMessage, new() where TMessageResponse : class, IMessage, new() { using var firstResponseCancellationTokenSource = new CancellationTokenSource(timeout); var firstResponseLock = new TaskCompletionSource <ExclusiveResponseMessage <TMessageRequest> >(TaskCreationOptions.RunContinuationsAsynchronously); using var _ = bus.Subscribe <ExclusiveResponseMessage <TMessageRequest> >(msg => { firstResponseLock.SetResult(msg); }, null); bus.Publish(new ExclusiveRequestMessage <TMessageRequest>(), null); var firstResponse = firstResponseLock.Task.WaitAsync(firstResponseCancellationTokenSource.Token).WaitAndUnwrapException(); if (firstResponse == null) { return(null); } using var responseCancellationTokenSource = new CancellationTokenSource(timeout); var responseLock = new TaskCompletionSource <ExclusiveAcceptedResponseMessage <TMessageResponse> >(TaskCreationOptions.RunContinuationsAsynchronously); using var __ = bus.Subscribe <ExclusiveAcceptedResponseMessage <TMessageResponse> >(msg => { responseLock.SetResult(msg); }, firstResponse.ReferenceId); bus.Publish(new ExclusiveAcceptedRequestMessage <TMessageRequest>(message), firstResponse.ReferenceId); var response = responseLock.Task.WaitAsync(responseCancellationTokenSource.Token).WaitAndUnwrapException(); return(response.Response); }
public static IDisposable SubscribeAndReplyToExclusive <TMessageRequest, TMessageResponse>(this INetworkBus bus, Func <TMessageRequest, Task <bool> > canReply, Func <TMessageRequest, Task <TMessageResponse> > func, Guid requestReferenceId) where TMessageRequest : notnull, IMessage, new() where TMessageResponse : notnull, IMessage, new() { var disposable1 = bus.Subscribe <ExclusiveRequestMessage <TMessageRequest> >(async message => { if (await canReply(message.Request)) { bus.Publish(new ExclusiveResponseMessage <TMessageRequest>(requestReferenceId), null); } }, null); var disposable2 = bus.SubscribeAndReply <ExclusiveAcceptedRequestMessage <TMessageRequest> >(async message => { return(new ExclusiveAcceptedResponseMessage <TMessageResponse>(await func(message.Request))); }, requestReferenceId); return(new CompositeDisposable(disposable1, disposable2)); }
public void Publish <T>(string topic, T payload) where T : class { var data = new byte[0]; // example, later use protobuf for serialisation if (typeof(T) == typeof(string)) { data = Encoding.UTF8.GetBytes((string)(object)payload); } else if (typeof(T).IsProto()) { // protobuf message using (var stream = new MemoryStream()) { Serializer.Serialize(stream, payload); data = stream.ToArray(); } } _networkBus.Publish(topic, data); }