public void DoesNotSendTransmissionForUnsupportedCodes()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 50,
                itemsAccepted: 45,
                errorCodes: new[] { "400", "402", "502", "409", "417" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        private void DelayFutureProcessing(HttpWebResponseWrapper response)
        {
            // Disable sending and buffer capacity (=EnqueueAsync will enqueue to the Storage)
            this.MaxSenderCapacity = 0;
            this.MaxBufferCapacity = 0;
            this.LogCapacityChanged();
            this.Apply();

            // Back-off for the Delay duration and enable sending capacity
            this.pauseTimer.Delay = this.GetBackOffTime(response.RetryAfterHeader);
            this.pauseTimer.Start(() =>
            {
                this.MaxBufferCapacity = null;
                this.MaxSenderCapacity = null;
                this.LogCapacityChanged();
                this.Apply();

                return TaskEx.FromResult<object>(null);
            });
        }
 public TransmissionProcessedEventArgs(Transmission transmission, Exception exception = null, HttpWebResponseWrapper response = null)
 {
     this.Transmission = transmission;
     this.Exception = exception;
     this.Response = response;
 }
            public void IsRaisedWhenTransmissionReturnsPartialSuccessResult()
            {
                var sender = new TransmissionSender();

                var eventIsRaised = new ManualResetEventSlim();
                object eventSender = null;
                TransmissionProcessedEventArgs eventArgs = null;
                sender.TransmissionSent += (s, a) =>
                {
                    eventSender = s;
                    eventArgs = a;
                    eventIsRaised.Set();
                };

                var wrapper = new HttpWebResponseWrapper();
                Transmission transmission = new StubTransmission { OnSend = () => wrapper };
                sender.Enqueue(() => transmission);

                Assert.True(eventIsRaised.Wait(50));
                Assert.Same(sender, eventSender);
                Assert.Same(transmission, eventArgs.Transmission);
                Assert.Same(wrapper, eventArgs.Response);
            }
        private async Task<HttpWebResponseWrapper> SendRequestAsync(WebRequest request)
        {
            using (Stream requestStream = await request.GetRequestStreamAsync().ConfigureAwait(false))
            {
                await requestStream.WriteAsync(this.Content, 0, this.Content.Length).ConfigureAwait(false);
            }

            using (WebResponse response = await request.GetResponseAsync().ConfigureAwait(false))
            {
                HttpWebResponseWrapper wrapper = null;
                
                var httpResponse = response as HttpWebResponse;
                if (httpResponse != null)
                {
                    // Return content only for 206 for performance reasons
                    // Currently we do not need it in other cases
                    if (httpResponse.StatusCode == HttpStatusCode.PartialContent)
                    {
                        wrapper = new HttpWebResponseWrapper
                        {
                            StatusCode = (int)httpResponse.StatusCode,
                        };

                        if (httpResponse.Headers != null)
                        {
                            wrapper.RetryAfterHeader = httpResponse.Headers["Retry-After"];
                        }

                        using (StreamReader content = new StreamReader(httpResponse.GetResponseStream()))
                        {
                            wrapper.Content = content.ReadToEnd();
                        }
                    }
                }

                return wrapper;
            }
        }
        public void IfItemIsRejectedOnlyThisItemIsUploadedBack()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 1,
                errorCodes: new[] { "429" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(1, enqueuedTransmissions.Count);
        }
        public void IfIndexMoreThanNumberOfItemsInTransmissionIgnoreError()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            // Index is 0-based
            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 1,
                errorCodes: new[] { "408" },
                indexStartWith: 1);

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        public void NewTransmissionCreatedByIndexesFromResponse()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry>
                {
                    new EventTelemetry("1"),
                    new EventTelemetry("2"),
                    new EventTelemetry("3"),
                };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 3,
                itemsAccepted: 1,
                errorCodes: new[] { "439", "439" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            string[] newItems = JsonSerializer
                .Deserialize(enqueuedTransmissions[0].Content)
                .Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            Assert.Equal(2, newItems.Length);
            Assert.True(newItems[0].Contains("\"name\":\"1\""));
            Assert.True(newItems[1].Contains("\"name\":\"2\""));
        }
        public void IfResponseIsBadJsonWeDoNotIncreaseErrorCount()
        {
            IList<Transmission> enqueuedTransmissions = new List<Transmission>();
            var transmitter = new StubTransmitter
            {
                OnEnqueue = t => { enqueuedTransmissions.Add(t); }
            };

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = "[,]";

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
            Assert.Equal(0, enqueuedTransmissions.Count);
        }
        public void IfNumberOfRecievedItemsEqualsToNumberOfAcceptedErrorsListIsIgnored()
        {
            var transmitter = new StubTransmitter();

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 2,
                itemsAccepted: 2,
                errorCodes: new[] { "408", "408" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(0, policy.ConsecutiveErrors);
        }
        public void IfMultipleItemsAreRejectedNumberOfErrorsIsIncreasedByOne()
        {
            // Number of errors determine backoff timeout.
            // When we get several bad items in one batch we want to increase errors by 1 only since it is one attempt to access Breeze

            var transmitter = new StubTransmitter();

            var policy = new PartialSuccessTransmissionPolicy();
            policy.Initialize(transmitter);

            var items = new List<ITelemetry> { new EventTelemetry(), new EventTelemetry() };
            Transmission transmission = new Transmission(new Uri("http://uri"), items, "type", "encoding");

            string response = this.GetBackendResponse(
                itemsReceived: 100,
                itemsAccepted: 95,
                errorCodes: new[] { "500", "500", "503", "503", "429" });

            var wrapper = new HttpWebResponseWrapper
            {
                StatusCode = 206,
                Content = response
            };

            transmitter.OnTransmissionSent(new TransmissionProcessedEventArgs(transmission, null, wrapper));

            Assert.Equal(1, policy.ConsecutiveErrors);
        }