public ApiDataSentEventArgs( Guid[] trackingIds, ApiData[] apiData, ISentApiData sentApiData) { TrackingIds = trackingIds; ApiData = apiData; SentApiData = sentApiData; }
public string[] Test(Guid trackingId, ApiData sourceData, ISentApiData sentApiData) { using (var stream = new MemoryStream(sentApiData.PayloadByteArray)) { return(Serializer.DeserializeItems <KancolleApiSendModel>(stream, PrefixStyle.Base128, 0).SelectMany(sendModel => { var targetData = this.ToApiData(sendModel); if (sourceData.RequestBody == targetData.RequestBody && sourceData.ResponseBody == targetData.ResponseBody) { double originalRequestByteCount = Encoding.UTF8.GetByteCount(sourceData.RequestBody); this.sumOriginalRequestByteCount += originalRequestByteCount; double originalResponseByteCount = Encoding.UTF8.GetByteCount(sourceData.ResponseBody); this.sumOriginalResponseByteCount += originalResponseByteCount; var originalByteCount = originalRequestByteCount + originalResponseByteCount; var sumOriginalByteCount = this.sumOriginalRequestByteCount + this.sumOriginalResponseByteCount; double modifiedRequestByteCount; using (var modifiedRequestStream = new MemoryStream()) { Serializer.Serialize(modifiedRequestStream, sendModel.RequestValuePatches); modifiedRequestByteCount = modifiedRequestStream.Length; } this.sumModifiedRequestByteCount += modifiedRequestByteCount; double modifiedResponseByteCount; using (var modifiedResponseStream = new MemoryStream()) { Serializer.Serialize(modifiedResponseStream, sendModel.ResponseValuePatches); modifiedResponseByteCount = modifiedResponseStream.Length; } this.sumModifiedResponseByteCount += modifiedResponseByteCount; var modifiedByteCount = modifiedRequestByteCount + modifiedResponseByteCount; var sumModifiedByteCount = this.sumModifiedRequestByteCount + this.sumModifiedResponseByteCount; return new[] { string.Format( "Req: {0,7} -> {1,7}, {2,7:0.00%}: {3,9} -> {4,9}, {5,7:0.00%}", originalRequestByteCount, modifiedRequestByteCount, modifiedRequestByteCount / originalRequestByteCount, this.sumOriginalRequestByteCount, this.sumModifiedRequestByteCount, this.sumModifiedRequestByteCount / this.sumOriginalRequestByteCount), string.Format( "Res: {0,7} -> {1,7}, {2,7:0.00%}: {3,9} -> {4,9}, {5,7:0.00%}", originalResponseByteCount, modifiedResponseByteCount, modifiedResponseByteCount / originalResponseByteCount, this.sumOriginalResponseByteCount, this.sumModifiedResponseByteCount, this.sumModifiedResponseByteCount / this.sumOriginalResponseByteCount), string.Format( "Both: {0,7} -> {1,7}, {2,7:0.00%}: {3,9} -> {4,9}, {5,7:0.00%}", originalByteCount, modifiedByteCount, modifiedByteCount / originalByteCount, sumOriginalByteCount, sumModifiedByteCount, sumModifiedByteCount / sumOriginalByteCount) }; } else { return new[] { "APIの復元に失敗しました。" }; } }).ToArray()); } }
public async Task SendingThread(CancellationToken cancellationToken) { try { var lastResult = TransferResult.Succeeded; var timeToDelay = TimeSpan.Zero; var rand = new Random(); while (!cancellationToken.IsCancellationRequested) { bool shouldWait = false; if (timeToDelay != TimeSpan.Zero) { try { await Task.Delay(timeToDelay, cancellationToken); } catch (OperationCanceledException) { break; } } lock (QueueLock) { shouldWait = Queue.Count == 0; } if (shouldWait) { try { SendEvent.WaitOne(); } catch (Exception ex) { this.FatalError(this, new FatalErrorEventArgs("Failed to wait event for sending data. Stopping sending.", ex)); break; } } if (cancellationToken.IsCancellationRequested) { break; } lock (QueueLock) { if (Queue.Count == 0) { continue; } } var itemsToSend = new List <QueueItem>(); lock (QueueLock) { if (DataSender.SupportsMultiPost) { itemsToSend.AddRange(Queue.Take(MaxChunkSize)); } else { itemsToSend.Add(Queue.Peek()); } } if (!itemsToSend.Any()) { continue; } var dataArray = itemsToSend.Select(x => x.ApiData).ToArray(); var trackingIds = itemsToSend.Select(x => x.TrackingId).ToArray(); try { this.ApiDataSending?.Invoke(this, new ApiDataSendingEventArgs(trackingIds, dataArray)); ISentApiData sentApiData = null; if (DataSender.SupportsMultiPost) { sentApiData = await DataSender.SendData(dataArray); } else { sentApiData = await DataSender.SendData(dataArray[0]); } lastResult = TransferResult.Succeeded; timeToDelay = TimeSpan.Zero; this.ApiDataSent?.Invoke(this, new ApiDataSentEventArgs(trackingIds, dataArray, sentApiData)); } catch (DataSendingException ex) { this.SendingError?.Invoke(this, new SendingErrorEventArgs(trackingIds, "Failed sending API data.", dataArray, ex)); switch (ex.Reason) { case SendingErrorReason.ServerError: if (lastResult == TransferResult.ServerError) { timeToDelay += ServerErrorDelayIncrement; if (timeToDelay > MaxDelayAfterServerkError) { timeToDelay = MaxDelayAfterServerkError; } } else { timeToDelay = MinDelayAfterServerkError; } lastResult = TransferResult.ServerError; break; case SendingErrorReason.HttpProtocolError: case SendingErrorReason.NetworkError: case SendingErrorReason.Unknown: if (lastResult == TransferResult.NetworkError) { timeToDelay += NetworkErrorDelayIncrement; if (timeToDelay > MaxDelayAfterNetworkError) { timeToDelay = MaxDelayAfterNetworkError; } } else { timeToDelay = MinDelayAfterNetworkError; } lastResult = TransferResult.NetworkError; break; } continue; } catch (OperationCanceledException) { break; } catch (Exception ex) { this.InternalError?.Invoke(this, new InternalErrorEventArgs(trackingIds, "Failed to something before sending API data.", ex, dataArray)); continue; } lock (QueueLock) { for (int i = 0; i < itemsToSend.Count && Queue.Count > 0; i++) { Queue.Dequeue(); } } } } catch (Exception ex) { FatalError?.Invoke(this, new FatalErrorEventArgs("Sending thread aborted. API data will no longer be sent from now.", ex)); } }