public static async Task <TMessageResponse?> PublishAndWaitForExclusiveResponseAsync <TMessageRequest, TMessageResponse>(this IAsyncNetworkBus 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 _ = await bus.SubscribeAsync <ExclusiveResponseMessage <TMessageRequest> >(msg => { firstResponseLock.SetResult(msg); return(Task.CompletedTask); }, null); await bus.PublishAsync(new ExclusiveRequestMessage <TMessageRequest>(), null); var firstResponse = await firstResponseLock.Task.WaitAsync(firstResponseCancellationTokenSource.Token); if (firstResponse == null) { return(null); } using var responseCancellationTokenSource = new CancellationTokenSource(timeout); var responseLock = new TaskCompletionSource <ExclusiveAcceptedResponseMessage <TMessageResponse> >(TaskCreationOptions.RunContinuationsAsynchronously); using var __ = await bus.SubscribeAsync <ExclusiveAcceptedResponseMessage <TMessageResponse> >(msg => { responseLock.SetResult(msg); return(Task.CompletedTask); }, firstResponse.ReferenceId); await bus.PublishAsync(new ExclusiveAcceptedRequestMessage <TMessageRequest>(message), firstResponse.ReferenceId); var response = await responseLock.Task.WaitAsync(responseCancellationTokenSource.Token); return(response.Response); }
public static async Task <IDisposable> SubscribeAndReplyToExclusive <TMessageRequest, TMessageResponse>(this IAsyncNetworkBus bus, Func <TMessageRequest, Task <bool> > canReply, Func <TMessageRequest, TMessageResponse> func, Guid requestReferenceId) where TMessageRequest : notnull, IMessage, new() where TMessageResponse : notnull, IMessage, new() { var disposable1 = await bus.SubscribeAsync <ExclusiveRequestMessage <TMessageRequest> >(async msg => { if (await canReply(msg.Request)) { await bus.PublishAsync(new ExclusiveResponseMessage <TMessageRequest>(requestReferenceId), null); } }, null); var disposable2 = await bus.SubscribeAndReplyAsync <ExclusiveAcceptedRequestMessage <TMessageRequest> >(msg => { return(Task.FromResult((IMessage) new ExclusiveAcceptedResponseMessage <TMessageResponse>(func(msg.Request)))); }, requestReferenceId); return(new CompositeDisposable(disposable1, disposable2)); }