protected virtual SendResult SaveRequestResults(Stream responseStream, TransportSendStats sendStats) { bool needRetry = false; TransportResponseStats responseStats; using (var streamReader = new StreamReader(responseStream)) using (var jsonReader = new JsonTextReader(streamReader)) { var jsonSerializer = new JsonSerializer(); // сохраним потоки данных конфигураций при десериализации jsonSerializer .Converters .Add(new ConfigurationsByteArraysToFilesConverter(this.configurationStore)); var response = jsonSerializer.Deserialize <TransportResponse>(jsonReader); this.sendStateStore.ConfigurationsUpdated(); // изменеилась статическая конфигурация if (response.StaticConfigData != null) { this.agentInfoService.SetStaticConfig(new TransportStaticConfig { ConfigToken = response.StaticConfigData.ConfigToken, ConfigVersion = response.StaticConfigData.ConfigVersion, }); return(SendResult.Retry(TransportConstants.DefaultUpdateStaticConfigTimeout)); } else { // изменилась бд системы (например сменили сервера) if (response.DbTokenData != null) { this.agentInfoService.SetDbToken(new TransportDbTokenData { DbToken = response.DbTokenData.DbToken }); this.packetManager.RemoveAll(); //return SendResult.Retry(TransportConstants.DefaultUpdateDbTokenTimeout); } responseStats = new TransportResponseStats() { SendedPacketsStats = sendStats.SendedPacketsStats, // изменилась бд системы TransferedPacketsProcessingResults = response.DbTokenData != null ? new List <TransferedPacketStats>() : sendStats.SendedPacketsStats.Select(x => { return(new TransferedPacketStats { PacketInfo = x.Key, SendStats = x.Value, Result = response.TransferedPackets.First(p => p.PacketId == x.Key.Id && p.ProviderKey == x.Key.ProviderKey).Result, }); }).ToList(), }; } } var packets = responseStats.TransferedPacketsProcessingResults.ToList(); foreach (var item in packets) { var packet = item.PacketInfo; if (item.Result == PacketProcessingResult.Saved) { this.packetManager.SaveSendStats(packet.ProviderKey, packet.Id, item.SendStats); } else if (item.Result == PacketProcessingResult.Error) { needRetry = true; } else if (item.Result == PacketProcessingResult.Resend) { // сбрасываем статистику this.packetManager.SaveSendStats(packet.ProviderKey, packet.Id, new SendStats()); } // игнорим эти результаты (если потом появится обработчик на сервере или обновиться агент до нормальной версии и в нём будет другая обработка, предполагаю что следующий набор данных будет доставлен успешно) //else if (item.Result == PacketProcessingResult.Unknown) //{ //} //else if (item.Result == PacketProcessingResult.NoProcessor) //{ //} else { this.packetManager.SaveSendStats(packet.ProviderKey, packet.Id, item.SendStats); } } //var configurations = stats.Configurations.ToList(); //foreach (var item in configurations) //{ //} return(needRetry ? SendResult.Retry(settings.ErrorRetryTimeout) : SendResult.Success()); }
protected virtual SendResult SendIteration(IList <ITransportPacketInfo> packetInfos, IList <ConfigurationRequestDataItem> configurationsToDownloadInfos, SendIterationContext context) { var url = this.GetUri(this.GetSendMessageHeaders(context)); string formDataBoundary = string.Format("----------{0:N}", Guid.NewGuid()); string contentType = "multipart/form-data; boundary=" + formDataBoundary; #if !NETSTANDARD2_0 try { var req = WebRequest.Create(url) as HttpWebRequest; //req.KeepAlive = true; //req.KeepAlive = false; req.AllowWriteStreamBuffering = false; req.Method = "POST"; req.ContentType = contentType; TransportSendStats sendededStats = null; using (Stream requestStream = req.GetRequestStream()) { sendededStats = this.WriteMessageToBody(formDataBoundary, requestStream, packetInfos, configurationsToDownloadInfos, context); } try { var response = req.GetResponse(); using (var resStream = response.GetResponseStream()) using (var streamReader = new StreamReader(resStream)) { // обрабатывает ответ return(this.SaveRequestResults(resStream, sendededStats)); } } catch (WebException ex) { var wRespStatusCode = ((HttpWebResponse)ex.Response).StatusCode; if ((int)wRespStatusCode == 429) { var timeout = int.TryParse(ex.Response.Headers.GetValues("Retry-After").FirstOrDefault(), out var retryTm) ? retryTm : Convert.ToInt64(settings.ErrorRetryTimeout.TotalMilliseconds); return(SendResult.Retry(timeout)); } // при общих ошибках return(SendResult.Retry(settings.ServerErrorRetryTimeout)); } } catch (Exception) { // при общих ошибках return(SendResult.Retry(settings.ErrorRetryTimeout)); } #else try { TransportSendStats sendededStats = null; var reqContent = new HttpRequestMessage(HttpMethod.Post, url) { Content = new WriteToStreamContent((requestStream, ctx) => { sendededStats = this.WriteMessageToBody(formDataBoundary, requestStream, packetInfos, configurationsToDownloadInfos, context); }), }; // workaround for net core 2.2 and analogs // нужно для того чтобы в случаях "отказов" не происходило чтение всего тела запроса, а читались только основные параметры reqContent.Headers.ExpectContinue = true; reqContent.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType); var result = this.httpClient.SendAsync(reqContent, HttpCompletionOption.ResponseContentRead).Result; if (result.IsSuccessStatusCode) { using (var stream = result.Content.ReadAsStreamAsync().Result) { // обрабатывает ответ return(this.SaveRequestResults(stream, sendededStats)); }; } else { if ((int)result.StatusCode == 429) { var timeout = int.TryParse(result.Headers.GetValues("Retry-After").FirstOrDefault(), out var retryTm) ? retryTm : Convert.ToInt64(settings.ErrorRetryTimeout.TotalMilliseconds); return(SendResult.Retry(timeout)); } return(SendResult.Retry(settings.ServerErrorRetryTimeout)); } } catch (Exception) { // при общих ошибках return(SendResult.Retry(settings.ErrorRetryTimeout)); } #endif }