/// <inheritdoc /> public async Task StartAsync() { try { await semaphore.WaitAsync(); if (_isStarted) { return; } _isStarted = true; await _client.Subscribe(response => { var correlationId = response.Headers.GetCorrelationHeader(); _log.LogTrace($"Get callback from cache {correlationId}"); var amqpResponse = Get(correlationId); if (amqpResponse == null) { var requestOptions = AmqpRequestOptions.DefaultOptions; requestOptions.CallType = AmqpCallType.Async; requestOptions.Timeout = 30; _log.LogTrace($"Callback not found {correlationId}. Create temporary callback. For {requestOptions.CallType.ToString()} type"); amqpResponse = new AmqpResponse { RequestOptions = requestOptions }; _callbacks.Set(correlationId, amqpResponse, amqpResponse.RequestOptions.Expires); _log.LogInformation($"Temporary save completed. correlationId {correlationId}."); } else { if (amqpResponse.Status == TaskStatus.Canceled) { _log.LogInformation($"Запрос {correlationId} был отменен. Удаление из очереди ожидания ответов"); _callbacks.Remove(correlationId); return(true); } } if (amqpResponse.RequestOptions.CallType == AmqpCallType.Rpc) { _log.LogTrace($"Parsing {correlationId}. {amqpResponse.RequestOptions.CallType} type. Remove callback"); _callbacks.Remove(correlationId); } amqpResponse.Response.SetResult(response); amqpResponse.EndTiming(TaskStatus.RanToCompletion); return(true); }); } finally { semaphore.Release(1); } }
public async Task <HttpResponseMessage> Send(Uri baseUri, HttpRequestMessage request, AmqpRequestOptions options) { CheckParams(baseUri, request); if (options == null) { options = AmqpRequestOptions.DefaultOptions; } var response = new AmqpResponse { RequestOptions = options }; var cancellationToken = new CancellationToken(); var cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(options.CancellationToken, cancellationToken); var competionSource = response.Response; if (options.CallType == AmqpCallType.Rpc && options.Timeout == 0) { options.Timeout = AmqpCommunication.RPC_TIMEOUT; _log.LogWarning( $"Call {AmqpCommunication.ProtocolName} by type {options.CallType} must be expired time. Set default value {options.Timeout}"); } var correlationId = request.Headers.GetCorrelationHeader(); if (!string.IsNullOrWhiteSpace(correlationId)) { if (options.CallType == AmqpCallType.Call) { options.Timeout = AmqpCommunication.Call_TIMEOUT; _log.LogInformation( $"Identifier callback set in headers. But calltype {options.CallType}. This type specified not sent response. Response will cached by {options.Timeout} CorrelationId {correlationId}."); } _callbacks.Set(correlationId, response, options.Expires); } try { await _client.Send(baseUri, request, options); if (options.CallType == AmqpCallType.Call) { _log.LogTrace( $"Call type {options.CallType}. Server not sent ansewer. Default http status set 200."); response.Response.SetResult(new HttpResponseMessage(HttpStatusCode.OK)); response.EndTiming(TaskStatus.RanToCompletion); } } catch (Exception e) { cancellationTokenSource.Cancel(); _log.LogError(e, "Request send error"); competionSource.SetException(new Exception($"no sent request to resource {baseUri} {request.RequestUri}", e)); response.EndTiming(TaskStatus.Faulted); response.Exception = e; return(await competionSource.Task); } await Task.WhenAny(competionSource.Task, Task.Delay(options.Expires, cancellationTokenSource.Token)); if (!competionSource.Task.IsCompleted) { response.EndTiming(TaskStatus.Canceled); competionSource.SetCanceled(); } return(await competionSource.Task); }