public virtual Task <Message> ExecuteOperation(OperationContext context) { int requestId = Interlocked.Increment(ref _requestId); context.Message.AttachHeader(new OperationHeader(requestId, OperationType.Request)); var continuation = new PendingOperation(requestId); if (!PendingOperationsByRequestId.TryAdd(requestId, continuation)) { throw new Exception("This could happen only if requestId is duplicated"); } var expiration = Task.Delay(TimeSpan.FromSeconds(ExpirationTimeout), continuation.Expiration.Token); expiration.ContinueWith((_) => { PendingOperation dummy; if (PendingOperationsByRequestId.TryRemove(continuation.RequestId, out dummy)) { continuation.TCS.SetException(new Exception(string.Format("ExecuteOperation<{0}, {1}> has Expired after {2} sec", requestId, context.Message, ExpirationTimeout))); } }); Log.Debug("Sending " + context.Message); Channel.Send(context.Message); MessageFactory.Free(context.Message); return(continuation.TCS.Task); }
public Task <Message> SendRequestAsync(Message request) { _requestsMeter.Mark(); //if operation header is already defined just use it eitherwise attach new one var opHeader = request.GetHeader <OperationHeader>(); Guid requestId = Guid.NewGuid(); if (opHeader == null) { request.AttachHeader(new OperationHeader(requestId, OperationType.Request, requestId)); } else { requestId = opHeader.RequestId; } Logger.NetChannelRequestStarted(Node, this, request, requestId); var continuation = new PendingOperation(requestId); if (!PendingOperationsByRequestId.TryAdd(requestId, continuation)) { throw new Exception("RequestId GUID is not unique"); } var expiration = Task.Delay(TimeSpan.FromSeconds(_config.SendTimeoutSec), continuation.Expiration.Token); expiration.ContinueWith((_) => { try { PendingOperation dummy; if (PendingOperationsByRequestId.TryRemove(continuation.RequestId, out dummy)) { _requestsFailedMeter.Mark(); Logger.NetChannelRequestTimedOut(Node, this, request, requestId, _config.SendTimeoutSec * 1000); if (!continuation.TCS.Task.IsCompleted) { continuation.TCS.SetException(new TimeoutException($"SendRequestAsync<{requestId}, {request}> has Expired after {_config.SendTimeoutSec} sec")); } } } catch {} }); Send(request); return(continuation.TCS.Task); }