/// <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); }
/// <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); }
/// <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); }