示例#1
0
        /// <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);
            }
        }
示例#2
0
        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);
        }