/// <summary>
        /// Asynchronously requests messages for the specified sport event and returns a request number used when issuing the request
        /// </summary>
        /// <param name="producer">An <see cref="IProducer"/> for which to make the recovery</param>
        /// <param name="eventId">A <see cref="URN"/> specifying the sport event for which to request the messages</param>
        /// <returns> <see cref="Task{HttpStatusCode}"/> representing the async operation</returns>
        public async Task <long> RecoverEventMessagesAsync(IProducer producer, URN eventId)
        {
            if (!producer.IsAvailable || producer.IsDisabled)
            {
                throw new ArgumentException($"Producer {producer} is disabled in the SDK", nameof(producer));
            }
            var requestNumber = _sequenceGenerator.GetNext();
            var _producer     = (Producer)producer;
            var url           = string.Format(EventMessagesRecoveryUrlFormat, _producer.ApiUrl, eventId, requestNumber);

            if (_nodeId != 0)
            {
                url = $"{url}&node_id={_nodeId}";
            }

            // await the result in case an exception is thrown
            var responseMessage = await _dataPoster.PostDataAsync(new Uri(url)).ConfigureAwait(false);

            if (!responseMessage.IsSuccessStatusCode)
            {
                throw new CommunicationException($"Recovery of event messages for Event={eventId}, RequestId={requestNumber}, failed with StatusCode={responseMessage.StatusCode}",
                                                 url,
                                                 responseMessage.StatusCode,
                                                 null);
            }

            _producer.EventRecoveries.TryAdd(requestNumber, eventId);
            return(requestNumber);
        }
Ejemplo n.º 2
0
        /// <summary>
        ///     Asynchronously gets a <see cref="Stream" /> containing data fetched from the provided <see cref="Uri" />
        /// </summary>
        /// <param name="uri">The <see cref="Uri" /> of the resource to be fetched</param>
        /// <returns>A <see cref="Task" /> which, when completed will return a <see cref="Stream" /> containing fetched data</returns>
        /// <exception cref="Sportradar.OddsFeed.SDK.Common.Exceptions.CommunicationException">Failed to execute http get</exception>
        public override async Task <Stream> GetDataAsync(Uri uri)
        {
            Metric.Context("FEED").Meter("LogHttpDataFetcher->GetDataAsync", Unit.Requests).Mark();

            var dataId =
                _sequenceGenerator.GetNext()
                .ToString("D7");     // because request can take long time, there may be several request at the same time; Id to know what belongs together.
            var watch = new Stopwatch();

            var logBuilder = new StringBuilder();

            logBuilder.Append("Id:").Append(dataId).Append(" Fetching url: ").Append(uri.AbsoluteUri);

            Stream responseStream;

            try
            {
                watch.Start();
                responseStream = await base.GetDataAsync(uri).ConfigureAwait(false);

                watch.Stop();
            }
            catch (Exception ex)
            {
                watch.Stop();
                if (ex.GetType() == typeof(CommunicationException))
                {
                    var commException = (CommunicationException)ex;
                    logBuilder.Append(" ResponseCode:").Append(commException.ResponseCode);
                    logBuilder.Append(" Duration:").Append(watch.Elapsed);
                    logBuilder.Append(" Response:").Append(commException.Response?.Replace("\n", string.Empty));
                    RestLog.Error(logBuilder);
                }

                throw;
            }

            logBuilder.Append(" Duration:").Append(watch.Elapsed);
            if (!RestLog.IsDebugEnabled)
            {
                RestLog.Info(logBuilder);
                return(responseStream);
            }

            var responseContent = new StreamReader(responseStream).ReadToEnd();

            responseContent = responseContent.Replace("\n", string.Empty);
            logBuilder.Append(" Response:").Append(responseContent);
            RestLog.Debug(logBuilder);

            var memoryStream = new MemoryStream();
            var writer       = new StreamWriter(memoryStream);

            writer.Write(responseContent);
            writer.Flush();
            memoryStream.Position = 0;
            return(memoryStream);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Asynchronously gets a <see cref="Stream" /> containing data fetched from the provided <see cref="Uri" />
        /// </summary>
        /// <param name="uri">The <see cref="Uri" /> of the resource to be fetched</param>
        /// <param name="authorization">The value of authorization header</param>
        /// <returns>A <see cref="Task" /> which, when completed will return a <see cref="Stream" /> containing fetched data</returns>
        /// <exception cref="CommunicationException">Failed to execute http get</exception>
        public override async Task <Stream> GetDataAsync(string authorization, Uri uri)
        {
            //Metric.Context("FEED").Meter("LogHttpDataFetcher->GetDataAsync", Unit.Requests).Mark();

            var dataId = _sequenceGenerator.GetNext().ToString("D7"); // because request can take long time, there may be several request at the same time; Id to know what belongs together.
            var watch  = new Stopwatch();

            RestLog.LogInformation($"Id:{dataId} Fetching url: {uri.AbsoluteUri}");
            watch.Start();

            Stream responseStream;

            try
            {
                responseStream = await base.GetDataAsync(authorization, uri).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                watch.Stop();
                RestLog.LogError($"Id:{dataId} Fetch error at {watch.ElapsedMilliseconds} ms.");
                if (ex.GetType() != typeof(ObjectDisposedException) && ex.GetType() != typeof(TaskCanceledException))
                {
                    RestLog.LogError(ex.Message, ex);
                }
                throw;
            }

            watch.Stop();
            if (!RestLog.IsEnabled(LogLevel.Debug))
            {
                return(responseStream);
            }

            var responseContent = new StreamReader(responseStream).ReadToEnd();

            var memoryStream = new MemoryStream();
            var writer       = new StreamWriter(memoryStream);

            writer.Write(responseContent);
            writer.Flush();
            memoryStream.Position = 0;

            RestLog.LogDebug($"Id:{dataId} Fetching from {uri.AbsoluteUri} took {watch.ElapsedMilliseconds} ms. Data={responseContent}");

            return(memoryStream);
        }
        /// <summary>
        /// Asynchronously requests messages for the specified sport event and returns a request number used when issuing the request
        /// </summary>
        /// <param name="producer">An <see cref="IProducer"/> for which to make the recovery</param>
        /// <param name="eventId">A <see cref="URN"/> specifying the sport event for which to request the messages</param>
        /// <returns> <see cref="Task{HttpStatusCode}"/> representing the async operation</returns>
        public async Task <long> RecoverEventMessagesAsync(IProducer producer, URN eventId)
        {
            Guard.Argument(producer, nameof(producer)).NotNull();
            Guard.Argument(eventId, nameof(eventId)).NotNull();

            if (!producer.IsAvailable || producer.IsDisabled)
            {
                throw new ArgumentException($"Producer {producer} is disabled in the SDK", nameof(producer));
            }
            var requestNumber = _sequenceGenerator.GetNext();
            var myProducer    = (Producer)producer;
            var url           = string.Format(EventMessagesRecoveryUrlFormat, myProducer.ApiUrl, eventId, requestNumber);

            if (_nodeId != 0)
            {
                url = $"{url}&node_id={_nodeId}";
            }

            // await the result in case an exception is thrown
            var responseMessage = await _dataPoster.PostDataAsync(new Uri(url)).ConfigureAwait(false);

            if (!responseMessage.IsSuccessStatusCode)
            {
                var message = $"Recovery of event messages for Event={eventId}, RequestId={requestNumber}, failed with StatusCode={responseMessage.StatusCode}";
                ExecutionLog.Error(message);
                _producerManager.InvokeRecoveryInitiated(new RecoveryInitiatedEventArgs(requestNumber, producer.Id, 0, eventId, message));
                throw new CommunicationException(message, url, responseMessage.StatusCode, null);
            }

            var messageOk = $"Recovery request of event messages for Event={eventId}, RequestId={requestNumber} succeeded.";

            ExecutionLog.Info(messageOk);
            myProducer.EventRecoveries.TryAdd(requestNumber, eventId);
            _producerManager.InvokeRecoveryInitiated(new RecoveryInitiatedEventArgs(requestNumber, producer.Id, 0, eventId, string.Empty));
            return(requestNumber);
        }