private void AddEvent(int key, long time)
        {
            var dataEvent = PartitionedStreamEvent.CreateInterval(key, time, time + IntervalLength, key);

            this.input.Add(dataEvent);

            UpdateExpectedLowWatermark(time);

            long localMin       = Math.Max(this.partitionHighWatermark[key] - this.ReorderLatency, this.lowWatermark);
            bool locallyOrdered = time >= localMin;
            long batchBorder    = localMin;

            if (locallyOrdered)
            {
                InsertSorted(key, dataEvent, (time == batchBorder) || this.ReorderLatency == 0);
            }
            else if (this.disorderPolicy.type == DisorderPolicyType.Drop || batchBorder >= dataEvent.EndTime)
            {
                AddDiagnostic(key, time); // Drop
            }
            else // Adjust
            {
                AddDiagnostic(key, time, batchBorder - dataEvent.SyncTime);
                var adjustedEvent = PartitionedStreamEvent.CreateInterval(key, batchBorder, dataEvent.EndTime, key);
                InsertSorted(key, adjustedEvent, true); // Since we adjust to batchBorder, batch immediately
            }

            this.highWatermark = Math.Max(this.highWatermark, time);
            this.partitionHighWatermark[key] = Math.Max(this.partitionHighWatermark[key], time);

            UpdateBatchMarker(key, batchBorder);
        }
Ejemplo n.º 2
0
        public void DisjointUnionNegativeWatermarkRepro()
        {
            const int leftKey  = 1;
            const int rightKey = 2;
            var       left     = new Subject <PartitionedStreamEvent <int, int> >();
            var       right    = new Subject <PartitionedStreamEvent <int, int> >();

            var qc         = new QueryContainer();
            var leftInput  = qc.RegisterInput(left);
            var rightInput = qc.RegisterInput(right);

            var actualOutput = new List <PartitionedStreamEvent <int, int> >();
            var inputs       = new IStreamable <PartitionKey <int>, int>[] { leftInput, rightInput };
            var union        = new MultiUnionStreamable <PartitionKey <int>, int>(inputs, guaranteedDisjoint: true);
            var egress       = qc.RegisterOutput(union).ForEachAsync(o => actualOutput.Add(o));
            var process      = qc.Restore();

            left.OnNext(PartitionedStreamEvent.CreatePoint(leftKey, 100, 1));
            right.OnNext(PartitionedStreamEvent.CreatePoint(rightKey, 100, 1));

            process.Flush();

            left.OnCompleted();
            right.OnCompleted();

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                PartitionedStreamEvent.CreatePoint(leftKey, 100, 1),
                PartitionedStreamEvent.CreatePoint(rightKey, 100, 1),
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            Assert.IsTrue(expected.SequenceEqual(actualOutput));
        }
        private void RunAndValidate()
        {
            // Flush
            AddEvent(0, 200);
            AddEvent(1, 200);
            AddEvent(2, 200);

            ProcessInput(out var diagnosticEvents, out var dataEvents);

            for (int key = 0; key < 3; key++)
            {
                var keyData      = dataEvents.Where(@event => @event.IsData && @event.PartitionKey == key).ToList();
                var expectedData = this.expected[key];
                Assert.IsTrue(expectedData.SequenceEqual(keyData));

                // Don't bother validating order of diagnostics
                var keyDiagnostic = diagnosticEvents.Where(@event => @event.Event.PartitionKey == key)
                                    .OrderBy(e => e.Event.SyncTime).ThenBy(e => e.Event.EndTime).ToList();
                var expectedDiagnostic = this.diagnostic[key].OrderBy(e => e.Event.SyncTime).ThenBy(e => e.Event.EndTime).ToList();
                Assert.IsTrue(expectedDiagnostic.SequenceEqual(keyDiagnostic));
            }
            var lowWatermarks = dataEvents.Where(@event => @event.IsLowWatermark).ToList();

            this.expectedLowWatermarks.Add(PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime));
            Assert.IsTrue(this.expectedLowWatermarks.SequenceEqual(lowWatermarks));
        }
        public void TestSetup(DisorderPolicy disorderPolicy, PeriodicLowWatermarkPolicy lowWatermarkPolicy)
        {
            this.disorderPolicy     = disorderPolicy;
            this.lowWatermarkPolicy = lowWatermarkPolicy;

            // This establishes three partitions with keys 0,1,2
            PartitionedStreamEvent <int, int> point;

            for (int key = 0; key < 3; key++)
            {
                point = PartitionedStreamEvent.CreatePoint(key, 0, key);
                this.input.Add(point);
                this.expected[key].Add(point);
                this.batchMarker[key] = 1;
            }

            // Add a point at 100 for key 0 as a baseline, and a low watermark if necessary
            this.highWatermark = 100;
            point = PartitionedStreamEvent.CreatePoint(0, this.highWatermark, 0);
            this.input.Add(point);
            UpdateExpectedLowWatermark(this.highWatermark);
            this.expected[0].Insert(this.batchMarker[0]++, point);

            // If we have a nonzero reorder latency, the event at 100 will be buffered, so add another point at
            // 100+ReorderLatency to push the real highwatermark to 100
            if (this.ReorderLatency > 0)
            {
                AddEvent(0, this.highWatermark + this.ReorderLatency);
            }
        }
Ejemplo n.º 5
0
        private void TumblingWindowWorker <TPayload>(
            Func <IPartitionedIngressStreamable <int, TPayload>, IStreamable <PartitionKey <int>, double> > createQuery,
            Func <int, long, TPayload> resultCreator)
        {
            SetupQuery(createQuery, out var input);

            input.OnNext(CreateInputInterval(key: 1, startTime: 120, resultCreator));
            input.OnNext(CreateInputInterval(key: 2, startTime: 120, resultCreator));

            input.OnNext(CreateInputInterval(key: 1, startTime: 150, resultCreator));

            input.OnNext(CreateInputInterval(key: 1, startTime: 250, resultCreator));
            input.OnNext(CreateInputInterval(key: 2, startTime: 250, resultCreator));

            input.OnCompleted();

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateLowWatermark <int, double>(100),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(200),

                CreateOutputInterval(key: 1, startTime: 200, endTime: 300, average: 135),
                CreateOutputInterval(key: 2, startTime: 200, endTime: 300, average: 120),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(300),

                CreateOutputInterval(key: 1, startTime: 300, endTime: 400, average: 250),
                CreateOutputInterval(key: 2, startTime: 300, endTime: 400, average: 250),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(input, expected);
        }
Ejemplo n.º 6
0
        public void PassThroughOutOfOrderWithPunctuation1()
        {
            var input = new PartitionedStreamEvent <int, int>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0),
                PartitionedStreamEvent.CreateStart(2, 2, 2),
                PartitionedStreamEvent.CreateStart(1, 1, 1),
                PartitionedStreamEvent.CreateStart(3, 3, 3),
                PartitionedStreamEvent.CreatePunctuation <int, int>(0, 1),
                PartitionedStreamEvent.CreatePunctuation <int, int>(1, 2),
                PartitionedStreamEvent.CreatePunctuation <int, int>(2, 3),
                PartitionedStreamEvent.CreatePunctuation <int, int>(3, 4),
            };
            var expected = new PartitionedStreamEvent <int, int>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0),
                PartitionedStreamEvent.CreateStart(2, 2, 2),
                PartitionedStreamEvent.CreateStart(1, 1, 1),
                PartitionedStreamEvent.CreateStart(3, 3, 3),
                PartitionedStreamEvent.CreatePunctuation <int, int>(0, 1),
                PartitionedStreamEvent.CreatePunctuation <int, int>(1, 2),
                PartitionedStreamEvent.CreatePunctuation <int, int>(2, 3),
                PartitionedStreamEvent.CreatePunctuation <int, int>(3, 4),
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            var output = Passthrough(input).ToList();

            Assert.IsTrue(expected.SequenceEqual(output));
        }
        public void FlushOnLowWatermarkDualStream()
        {
            SetupQuery(DisorderPolicy.Throw(reorderLatency: 500));

            // These will be buffered due to reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0));    // key 0: 1-2
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 101, 0));  // key 0: 101-102

            // This will batch the first point (0: 1-2)); but the second point ( key 0: 101-102) remains batched, since 101 > 100.
            // Since we use the default policy, FlushOnLowWatermark, the first point will also be flushed at this point.
            this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(100));

            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1005, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1100, 0));

            // OnCompletedPolicy.EndOfStream adds the last two points to the batch then flushes all

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Flushed in response to low watermark
                PartitionedStreamEvent.CreatePoint(0, 1, 0),
                PartitionedStreamEvent.CreateLowWatermark <int, int>(100),

                // Flushed in response to OnCompleted
                PartitionedStreamEvent.CreatePoint(0, 101, 0),
                PartitionedStreamEvent.CreatePoint(0, 1005, 0),
                PartitionedStreamEvent.CreatePoint(0, 1100, 0),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
Ejemplo n.º 8
0
        public void SumSessionWindow()
        {
            var input = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreatePoint(0, 0, 1.0),
                PartitionedStreamEvent.CreatePoint(0, 1, 2.0),
                PartitionedStreamEvent.CreatePoint(0, 2, 3.0),
                PartitionedStreamEvent.CreatePoint(0, 5, 4.0),
                PartitionedStreamEvent.CreatePoint(0, 6, 5.0),
                PartitionedStreamEvent.CreatePoint(0, 9, 6.0),
            };

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 1.0),
                PartitionedStreamEvent.CreateEnd(0, 1, 0, 1.0),
                PartitionedStreamEvent.CreateStart(0, 1, 3.0),
                PartitionedStreamEvent.CreateEnd(0, 2, 1, 3.0),
                PartitionedStreamEvent.CreateStart(0, 2, 6.0),
                PartitionedStreamEvent.CreateEnd(0, 4, 2, 6.0),
                PartitionedStreamEvent.CreateStart(0, 5, 4.0),
                PartitionedStreamEvent.CreateEnd(0, 6, 5, 4.0),
                PartitionedStreamEvent.CreateStart(0, 6, 9.0),
                PartitionedStreamEvent.CreateEnd(0, 8, 6, 9.0),
                PartitionedStreamEvent.CreateStart(0, 9, 6.0),
                PartitionedStreamEvent.CreateEnd(0, 11, 9, 6.0),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            var output = SessionWindowSum(input, 2, 5).ToArray();

            Assert.IsTrue(expected.SequenceEqual(output));
        }
Ejemplo n.º 9
0
        private static void PartitionedStartEdgeJoinTest()
        {
            var input1 = new[]
            {
                PartitionedStreamEvent.CreateStart("Partition1", 100, "A1"),
                PartitionedStreamEvent.CreateStart("Partition1", 101, "B1"),
                PartitionedStreamEvent.CreateStart("Partition1", 102, "C1"),

                PartitionedStreamEvent.CreateStart("Partition2", 100, "A1"),
                PartitionedStreamEvent.CreateStart("Partition2", 101, "B1"),
                PartitionedStreamEvent.CreateStart("Partition2", 102, "C1"),
            };

            var input2 = new[]
            {
                PartitionedStreamEvent.CreateStart("Partition1", 105, "A2"),
                PartitionedStreamEvent.CreateStart("Partition1", 106, "B2"),
                PartitionedStreamEvent.CreateStart("Partition1", 107, "D2"),

                PartitionedStreamEvent.CreateStart("Partition2", 108, "A2"),
                PartitionedStreamEvent.CreateStart("Partition2", 109, "D2"),
                PartitionedStreamEvent.CreateStart("Partition2", 110, "C2"),
            };

            // Set properties to start-edge only
            var inputStream1 = input1.ToObservable().ToStreamable();

            inputStream1.Properties.IsConstantDuration     = true;
            inputStream1.Properties.ConstantDurationLength = StreamEvent.InfinitySyncTime;
            var inputStream2 = input2.ToObservable().ToStreamable();

            inputStream2.Properties.IsConstantDuration     = true;
            inputStream2.Properties.ConstantDurationLength = StreamEvent.InfinitySyncTime;

            var output = new List <PartitionedStreamEvent <string, string> >();

            inputStream1
            .Join(
                inputStream2,
                l => (l != null ? l[0].ToString() : null),
                r => (r != null ? r[0].ToString() : null),
                (l, r) => l + "," + r)
            .ToStreamEventObservable()
            .ForEachAsync(e => output.Add(e))
            .Wait();

            var correct = new[]
            {
                PartitionedStreamEvent.CreateStart("Partition1", 105, "A1,A2"),
                PartitionedStreamEvent.CreateStart("Partition1", 106, "B1,B2"),

                PartitionedStreamEvent.CreateStart("Partition2", 108, "A1,A2"),
                PartitionedStreamEvent.CreateStart("Partition2", 110, "C1,C2"),

                PartitionedStreamEvent.CreateLowWatermark <string, string>(StreamEvent.InfinitySyncTime)
            };

            Assert.IsTrue(output.SequenceEqual(correct));
        }
Ejemplo n.º 10
0
        public void AverageSessionWindow()
        {
            var input = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 1.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(0, 8, 4.0),
                PartitionedStreamEvent.CreateStart(0, 9, 7.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 8, 2.0),
                PartitionedStreamEvent.CreateStart(2, 20, 3.0),
                PartitionedStreamEvent.CreateStart(2, 22, 4.0),
                PartitionedStreamEvent.CreateStart(3, 3, 3.0),
                PartitionedStreamEvent.CreateStart(3, 4, 4.0),
                PartitionedStreamEvent.CreateStart(3, 5, 5.0),
            };

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateEnd(0, 1, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 0.5),
                PartitionedStreamEvent.CreateEnd(0, 2, 1, 0.5),
                PartitionedStreamEvent.CreateStart(0, 2, 1.0),
                PartitionedStreamEvent.CreateEnd(0, 7, 2, 1.0),
                PartitionedStreamEvent.CreateStart(0, 8, 4.0),
                PartitionedStreamEvent.CreateEnd(0, 9, 8, 4.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateEnd(1, 2, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 1.5),
                PartitionedStreamEvent.CreateEnd(1, 3, 2, 1.5),
                PartitionedStreamEvent.CreateStart(2, 8, 2.0),
                PartitionedStreamEvent.CreateEnd(2, 13, 8, 2.0),
                PartitionedStreamEvent.CreateStart(2, 20, 3.0),
                PartitionedStreamEvent.CreateEnd(2, 22, 20, 3.0),
                PartitionedStreamEvent.CreateStart(3, 3, 3.0),
                PartitionedStreamEvent.CreateEnd(3, 4, 3, 3.0),
                PartitionedStreamEvent.CreateStart(3, 4, 3.5),
                PartitionedStreamEvent.CreateEnd(3, 5, 4, 3.5),
                PartitionedStreamEvent.CreateStart(0, 9, 5.5),
                PartitionedStreamEvent.CreateEnd(0, 14, 9, 5.5),
                PartitionedStreamEvent.CreateStart(1, 3, 2.0),
                PartitionedStreamEvent.CreateEnd(1, 8, 3, 2.0),
                PartitionedStreamEvent.CreateStart(2, 22, 3.5),
                PartitionedStreamEvent.CreateEnd(2, 27, 22, 3.5),
                PartitionedStreamEvent.CreateStart(3, 5, 4.0),
                PartitionedStreamEvent.CreateEnd(3, 10, 5, 4.0),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            var output = SessionWindowAverage(input, 5, 10);

            Assert.IsTrue(expected.SequenceEqual(output));
        }
Ejemplo n.º 11
0
        public void Union0()
        {
            var input1 = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 1.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 4, 4.0),
            };

            var input2 = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(2, 0, 0.0),
                PartitionedStreamEvent.CreateStart(2, 1, 1.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(0, 3, 3.0),
                PartitionedStreamEvent.CreateStart(0, 4, 4.0),
            };

            var output = Union(input1, input2).ToArray();

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateStart(2, 0, 0.0),
                PartitionedStreamEvent.CreateStart(2, 1, 1.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 4, 4.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(0, 1, 1.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(0, 3, 3.0),
                PartitionedStreamEvent.CreateStart(0, 4, 4.0),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            Assert.IsTrue(expected.SequenceEqual(output));
        }
Ejemplo n.º 12
0
        private void HoppingWindowWorker <TPayload>(
            Func <IPartitionedIngressStreamable <int, TPayload>, IStreamable <PartitionKey <int>, double> > createQuery,
            Func <int, long, TPayload> resultCreator)
        {
            SetupQuery(createQuery, out var input);

            // Establish two partitions with keys 1,2
            input.OnNext(CreateInputInterval(key: 1, startTime: 100, resultCreator));
            input.OnNext(CreateInputInterval(key: 2, startTime: 100, resultCreator));

            // Move partition 1 ahead, generating a low watermark at 150 (due to the lifetime alteration of hopping window).
            // Partition 2 should not be cleaned up, since it still contains data in its sliding window
            input.OnNext(CreateInputInterval(key: 1, startTime: 150, resultCreator));

            // Move partition 1 ahead again, generating a low watermark at 250-20=230. Partition 2 can now be cleaned up,
            // since it no longer contains data in its sliding window
            input.OnNext(CreateInputInterval(key: 1, startTime: 250, resultCreator));

            // Reactivate partition 2, which should start with a clean slate
            input.OnNext(CreateInputInterval(key: 2, startTime: 250, resultCreator));

            input.OnCompleted();

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                // Two partitions established with new hop window starting at 100
                PartitionedStreamEvent.CreateLowWatermark <int, double>(100),
                CreateOutputStart(key: 1, startTime: 100, average: 100),
                CreateOutputStart(key: 2, startTime: 100, average: 100),

                // New event for partition 1's sliding window (150), establishes a new hop window starting at 150
                PartitionedStreamEvent.CreateLowWatermark <int, double>(150),
                CreateOutputEnd(key: 1, endTime: 150, originalStart: 100, average: 100),
                CreateOutputStart(key: 1, startTime: 150, average: 125),    // Average(100, 150)=125

                // New event for partition 1's sliding window (250) creates a low watermark, which  deaccumulates
                // both events at startTime 100. Partition 2 can be cleaned up (no more data), but partition 1 should
                // see its average updated to exclude the 100.
                CreateOutputEnd(key: 1, endTime: 200, originalStart: 150, average: 125),
                CreateOutputEnd(key: 2, endTime: 200, originalStart: 100, average: 100),

                CreateOutputStart(key: 1, startTime: 200, average: 150),    // Average(150)=150
                CreateOutputEnd(key: 1, endTime: 250, originalStart: 200, average: 150),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(250),

                // OnCompletedPolicy.EndOfStream - Both partitions accumulate the 250
                CreateOutputStart(key: 1, startTime: 250, average: 250),    // Average(250)=250
                CreateOutputStart(key: 2, startTime: 250, average: 250),    // Average(250)=250
                CreateOutputEnd(key: 1, endTime: 350, originalStart: 250, average: 250),
                CreateOutputEnd(key: 2, endTime: 350, originalStart: 250, average: 250),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(input, expected);
        }
Ejemplo n.º 13
0
        public void PassThroughEmpty()
        {
            var input = Array.Empty <PartitionedStreamEvent <int, int> >();

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };
            var output = Passthrough(input).ToList();

            Assert.IsTrue(expected.SequenceEqual(output));
        }
Ejemplo n.º 14
0
        public void AlterLifeTimeWithFlushDoubles()
        {
            var startDate = new DateTime(100);
            var data      = new[]
            {
                new { Time = startDate, DeviceId = 4, Value = 4 },
                new { Time = startDate, DeviceId = 4, Value = 4 },
                new { Time = startDate, DeviceId = 6, Value = 6 },
                new { Time = startDate, DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(1), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(1), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(2), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(2), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(3), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(3), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(11), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(11), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(5), DeviceId = 4, Value = 4 },
                new { Time = startDate.AddMinutes(5), DeviceId = 4, Value = 4 },
                new { Time = startDate.AddMinutes(12), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(12), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(13), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(13), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(14), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(14), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(15), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(15), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(16), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(16), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(17), DeviceId = 4, Value = 4 },
                new { Time = startDate.AddMinutes(17), DeviceId = 4, Value = 4 },
                new { Time = startDate.AddMinutes(21), DeviceId = 6, Value = 6 },
                new { Time = startDate.AddMinutes(21), DeviceId = 6, Value = 6 },
            }
            .Select(e => PartitionedStreamEvent.CreateInterval(e.DeviceId, e.Time.Ticks, StreamEvent.MaxSyncTime, e.Value));

            var res = new List <Notification <PartitionedStreamEvent <int, int> > >();

            using (data.ToObservable()
                   .ToStreamable(
                       DisorderPolicy.Adjust(0),
                       PartitionedFlushPolicy.FlushOnLowWatermark,
                       PeriodicPunctuationPolicy.Time(36000))
                   .AlterEventDuration(1)
                   .ToStreamEventObservable()
                   .Subscribe(res.NotificationListObserver()))
            {
            }

            Assert.IsTrue(res.Count > 0, "There should be some results.");
        }
        public void ReorderLatencyWithExplicitPunctuation()
        {
            var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10);

            SetupQuery(disorderPolicy);

            // These will be buffered and reordered due to reorderLatency of 10
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0));

            // This will update partition 0's current time to 30. Anything before 30 after this point will be out of order.
            this.input.OnNext(PartitionedStreamEvent.CreatePunctuation <int, int>(0, 30));

            // Even though these events are before the partitions high watermark (30) - reorder latency (10) = 20,
            // they will still be dropped due to the punctuation at 30.
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0));

            // Events at or after the punctuation are still valid
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 35, 0));

            // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Events are reordered within the reorderLatency
                PartitionedStreamEvent.CreatePoint(0, 20, 0),
                PartitionedStreamEvent.CreatePoint(0, 25, 0),
                PartitionedStreamEvent.CreatePoint(0, 30, 0),

                PartitionedStreamEvent.CreatePunctuation <int, int>(0, 30),
                PartitionedStreamEvent.CreatePoint(0, 30, 0),
                PartitionedStreamEvent.CreatePoint(0, 35, 0),

                // Each partition acts independently
                PartitionedStreamEvent.CreatePoint(1, 1, 0),
                PartitionedStreamEvent.CreatePoint(1, 5, 0),
                PartitionedStreamEvent.CreatePoint(1, 10, 0),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
Ejemplo n.º 16
0
        public void SorterDequeueUntillRow()
        {
            var oldSortingTechnique = Config.IngressSortingTechnique;

            Config.IngressSortingTechnique = SortingTechnique.ImpatienceSort;

            var input = new List <Tuple <int, int> >()
            {
                Tuple.Create(0, 1),
                Tuple.Create(1, 1),
                Tuple.Create(0, 3),
                Tuple.Create(0, 5),
                Tuple.Create(1, 3),
                Tuple.Create(1, 20),
                Tuple.Create(0, 6),
                Tuple.Create(0, 7),
                Tuple.Create(0, 8),
                Tuple.Create(1, 2),
                Tuple.Create(0, 2),
                Tuple.Create(1, 30),
                Tuple.Create(0, 13)
            };

            var expectedoutput = new List <Tuple <int, int> >()
            {
                Tuple.Create(1, 1),
                Tuple.Create(1, 3),
                Tuple.Create(1, 20),
                Tuple.Create(0, 1),
                Tuple.Create(0, 2),
                Tuple.Create(0, 3),
                Tuple.Create(0, 5),
                Tuple.Create(0, 6),
                Tuple.Create(0, 7),
                Tuple.Create(0, 8),
                Tuple.Create(0, 13),
                Tuple.Create(1, 30)
            };

            var prog = input.Select(x => PartitionedStreamEvent.CreateStart(x.Item1, x.Item2, x.Item2)).ToObservable()
                       .ToStreamable(DisorderPolicy.Drop(10)).ToStreamEventObservable();
            var outevents = prog.ToEnumerable().ToList();
            var output    = outevents.Where(o => o.IsData).ToList();
            var success   = output.SequenceEqual(expectedoutput.Select(t => PartitionedStreamEvent.CreateStart(t.Item1, t.Item2, t.Item2)));

            Config.IngressSortingTechnique = oldSortingTechnique;

            Assert.IsTrue(success);
        }
Ejemplo n.º 17
0
        public void Enqueue(ref PartitionedStreamEvent <TKey, TPayload> streamEvent)
        {
            ImpatienceSorter sorter;

            if (!this.sorters.Lookup(streamEvent.PartitionKey, out int index))
            {
                sorter = new ImpatienceSorter();
                this.sorters.Insert(ref index, streamEvent.PartitionKey, sorter);
            }
            else
            {
                sorter = this.sorters.entries[index].value;
            }

            sorter.Enqueue(ref streamEvent);
        }
Ejemplo n.º 18
0
        public void AverageGeneral()
        {
            var input = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 1.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 4, 4.0),
                PartitionedStreamEvent.CreateStart(3, 3, 3.0),
                PartitionedStreamEvent.CreateStart(3, 4, 4.0),
                PartitionedStreamEvent.CreateStart(3, 5, 5.0),
            };

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateEnd(0, 1, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 0.5),
                PartitionedStreamEvent.CreateEnd(0, 2, 1, 0.5),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateEnd(1, 2, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 1.5),
                PartitionedStreamEvent.CreateEnd(1, 3, 2, 1.5),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateEnd(2, 3, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 3, 2.5),
                PartitionedStreamEvent.CreateEnd(2, 4, 3, 2.5),
                PartitionedStreamEvent.CreateStart(3, 3, 3.0),
                PartitionedStreamEvent.CreateEnd(3, 4, 3, 3.0),
                PartitionedStreamEvent.CreateStart(3, 4, 3.5),
                PartitionedStreamEvent.CreateEnd(3, 5, 4, 3.5),
                PartitionedStreamEvent.CreateStart(0, 2, 1.0),
                PartitionedStreamEvent.CreateStart(1, 3, 2.0),
                PartitionedStreamEvent.CreateStart(2, 4, 3.0),
                PartitionedStreamEvent.CreateStart(3, 5, 4.0),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            var output = AverageGeneral(input).ToList();

            Assert.IsTrue(expected.SequenceEqual(output));
        }
        private void InsertSorted(int key, PartitionedStreamEvent <int, int> dataEvent, bool batchImmediately)
        {
            if (batchImmediately)
            {
                this.expected[key].Insert(this.batchMarker[key]++, dataEvent);
            }
            else
            {
                int index = this.batchMarker[key];
                while (index < this.expected[key].Count && this.expected[key][index].SyncTime < dataEvent.SyncTime)
                {
                    index++;
                }

                this.expected[key].Insert(index, dataEvent);
            }
        }
Ejemplo n.º 20
0
            public void Enqueue(ref PartitionedStreamEvent <TKey, TPayload> streamEvent)
            {
                int loc;

                if (streamEvent.SyncTime >= this.Tails[0])
                {
                    loc = 0;
                }
                else
                {
                    loc = BinarySearch(streamEvent.SyncTime);
                }

                // Add a new queue
                if (loc == this.NumFibers)
                {
                    // Double space to support more queues
                    if (this.NumFibers >= this.MaxFibers)
                    {
                        long[] tmp = new long[this.MaxFibers * 2];
                        Array.Copy(this.Tails, tmp, this.MaxFibers);
                        this.Tails = tmp;

                        this.MaxFibers = this.MaxFibers * 2;

                        this.MergeSource = new PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > [this.MaxFibers];
                    }

                    // Add new queue
                    this.ecbPool.Get(out PooledElasticCircularBuffer <PartitionedStreamEvent <TKey, TPayload> > ecb);
                    this.Fibers.Add(ecb);
                    this.NumFibers++;
                }

                this.Fibers[loc].Enqueue(ref streamEvent);
                if ((loc > 0) && (this.Fibers[loc].Count == 1))
                {
                    if (streamEvent.SyncTime < this.NextAffectingSyncTime)
                    {
                        this.NextAffectingSyncTime = streamEvent.SyncTime;
                    }
                }

                this.Tails[loc] = streamEvent.SyncTime;
            }
        public void ReorderLatencyAdjust()
        {
            var disorderPolicy = DisorderPolicy.Adjust(reorderLatency: 10);

            SetupQuery(disorderPolicy);

            // These will be buffered and reordered due to reorderLatency of 10
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0));

            // These will be adjusted to the minimum, since they are before the partition's high watermark (30) - reorder latency (10) = 20
            this.input.OnNext(PartitionedStreamEvent.CreateInterval(0, 8, 30, 0)); // Will be adjusted to 20
            this.input.OnNext(PartitionedStreamEvent.CreateInterval(0, 9, 30, 0)); // Will be adjusted to 20

            // This will be dropped, since Trill will not adjust intervals whose end times are before the minimum
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 8, 0)); // Will be dropped
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 9, 0)); // Will be dropped

            // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Events are reordered within the reorderLatency, and out of order events are adjusted to minimum
                PartitionedStreamEvent.CreatePoint(0, 20, 0),
                PartitionedStreamEvent.CreateInterval(0, 20, 30, 0),
                PartitionedStreamEvent.CreateInterval(0, 20, 30, 0),
                PartitionedStreamEvent.CreatePoint(0, 25, 0),
                PartitionedStreamEvent.CreatePoint(0, 30, 0),

                // Each partition acts independently
                PartitionedStreamEvent.CreatePoint(1, 1, 0),
                PartitionedStreamEvent.CreatePoint(1, 5, 0),
                PartitionedStreamEvent.CreatePoint(1, 10, 0),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
Ejemplo n.º 22
0
        public IEnumerable <index_t> Parse()
        {
            using var reader = new StreamReader(filename);
            var index = new List <index_t>();

            while (!reader.EndOfStream)
            {
                var line = reader.ReadLine();
                if (line != null)
                {
                    var values = line.Split(',');
                    var devid  = values[1].Trim();
                    var s      = long.Parse(values[2]);
                    var e      = long.Parse(values[3]);
                    index.Add(PartitionedStreamEvent.CreateInterval(devid, s, e, Unit.Default));
                }
            }

            return(index);
        }
        private void UpdateExpectedLowWatermark(long eventTime)
        {
            if (this.GenerateLowWatermarks && eventTime > this.Lag)
            {
                var newLowWatermarkTime = eventTime - this.Lag;
                if (newLowWatermarkTime >= this.lowWatermark + this.GenerationPeriod && newLowWatermarkTime > this.lowWatermark)
                {
                    // eventTime is sufficiently high to generate a new watermark, but first snap it to the nearest generationPeriod boundary
                    newLowWatermarkTime = newLowWatermarkTime.SnapToLeftBoundary((long)this.lowWatermarkPolicy.generationPeriod);
                    this.lowWatermark   = newLowWatermarkTime;
                    for (int key = 0; key < 3; key++)
                    {
                        this.partitionHighWatermark[key] = Math.Max(this.partitionHighWatermark[key], newLowWatermarkTime);
                        UpdateBatchMarker(key, newLowWatermarkTime);
                    }

                    this.expectedLowWatermarks.Add(PartitionedStreamEvent.CreateLowWatermark <int, int>(newLowWatermarkTime));
                }
            }
        }
        public void FlushOnLowWatermarkSimple()
        {
            SetupQuery(DisorderPolicy.Throw(reorderLatency: 10), PartitionedFlushPolicy.FlushOnLowWatermark,
                       null, null, OnCompletedPolicy.None);

            // This will be buffered due to reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0));

            // Since we specify FlushOnLowWatermark, this will flush the point above, as well as the low watermark itself
            this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(9000));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Flushed in response to low watermark
                PartitionedStreamEvent.CreatePoint(0, 1, 0),
                PartitionedStreamEvent.CreateLowWatermark <int, int>(9000),
            };

            FinishQuery(expected);
        }
        public void LowWatermark()
        {
            var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10);

            SetupQuery(disorderPolicy, PartitionedFlushPolicy.None);

            // This will be buffered due to reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 1, 0));

            // This will set the entire stream's lower bound to 100
            this.input.OnNext(PartitionedStreamEvent.CreateLowWatermark <int, int>(100));

            // If any partition, new or existing, specifies a timestamp before 100, it is considered out of order
            // and since we specify DisorderPolicy.Drop, they will be dropped
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 50, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 50, 0));

            // Any points at or after the low watermark of 100 will be processed as usual
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 100, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 100, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 105, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 105, 0));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Flushed in response to the default OnCompletedPolicy.EndOfStream
                PartitionedStreamEvent.CreatePoint(0, 1, 0),
                PartitionedStreamEvent.CreateLowWatermark <int, int>(100),

                // Points at time 50 are dropped
                PartitionedStreamEvent.CreatePoint(0, 100, 0),
                PartitionedStreamEvent.CreatePoint(1, 100, 0),
                PartitionedStreamEvent.CreatePoint(0, 105, 0),
                PartitionedStreamEvent.CreatePoint(1, 105, 0),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
        public void PunctuationTimeGeneration()
        {
            SetupQuery(
                DisorderPolicy.Throw(),
                PartitionedFlushPolicy.FlushOnLowWatermark,
                PeriodicPunctuationPolicy.Time(generationPeriod: 1000));

            // This establishes three partitions with keys 1,2,3
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 0, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 0, 1));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 0, 2));

            // Since the next point arrives at 10001, which is exactly PeriodicPunctuationPolicy.generationPeriod after
            // the first point, this will generate a punctuation at 10001
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 10001, 0));

            // These are still valid, since the punctuation generated above only affects key 0
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 1));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(2, 1, 2));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Flushed in response to OnCompleted
                PartitionedStreamEvent.CreatePoint(0, 0, 0),
                PartitionedStreamEvent.CreatePoint(1, 0, 1),
                PartitionedStreamEvent.CreatePoint(2, 0, 2),

                // Punctuation snapped to the leftmost generationPeriod boundary
                PartitionedStreamEvent.CreatePunctuation <int, int>(0, 10000),
                PartitionedStreamEvent.CreatePoint(0, 10001, 0),

                PartitionedStreamEvent.CreatePoint(1, 1, 1),
                PartitionedStreamEvent.CreatePoint(2, 1, 2),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
Ejemplo n.º 27
0
        public void AverageTumblingWindow()
        {
            var input = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateStart(0, 0, 0.0),
                PartitionedStreamEvent.CreateStart(0, 1, 1.0),
                PartitionedStreamEvent.CreateStart(0, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 1, 1.0),
                PartitionedStreamEvent.CreateStart(1, 2, 2.0),
                PartitionedStreamEvent.CreateStart(1, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 2, 2.0),
                PartitionedStreamEvent.CreateStart(2, 3, 3.0),
                PartitionedStreamEvent.CreateStart(2, 4, 4.0),
                PartitionedStreamEvent.CreateStart(3, 3, 3.0),
                PartitionedStreamEvent.CreateStart(3, 4, 4.0),
                PartitionedStreamEvent.CreateStart(3, 5, 5.0),
            };

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateInterval(0, 0, 1, 0.0),
                PartitionedStreamEvent.CreateInterval(0, 1, 2, 1.0),
                PartitionedStreamEvent.CreateInterval(1, 1, 2, 1.0),
                PartitionedStreamEvent.CreateInterval(1, 2, 3, 2.0),
                PartitionedStreamEvent.CreateInterval(2, 2, 3, 2.0),
                PartitionedStreamEvent.CreateInterval(2, 3, 4, 3.0),
                PartitionedStreamEvent.CreateInterval(3, 3, 4, 3.0),
                PartitionedStreamEvent.CreateInterval(3, 4, 5, 4.0),
                PartitionedStreamEvent.CreateInterval(0, 2, 3, 2.0),
                PartitionedStreamEvent.CreateInterval(1, 3, 4, 3.0),
                PartitionedStreamEvent.CreateInterval(2, 4, 5, 4.0),
                PartitionedStreamEvent.CreateInterval(3, 5, 6, 5.0),
                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            var output = TumblingWindow(input);

            Assert.IsTrue(expected.SequenceEqual(output));
        }
        public void ReorderLatencyDrop()
        {
            var disorderPolicy = DisorderPolicy.Drop(reorderLatency: 10);

            SetupQuery(disorderPolicy);

            // These will be buffered and reordered due to reorderLatency of 10
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 30, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 25, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 20, 0));

            // These will be dropped since they are before the partition's high watermark (30) - reorder latency (10) = 20
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 8, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(0, 9, 0));

            // Each partition is independent, so a new partition is unaffected by another's high watermark/reorderLatency
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 1, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 10, 0));
            this.input.OnNext(PartitionedStreamEvent.CreatePoint(1, 5, 0));

            var expected = new PartitionedStreamEvent <int, int>[]
            {
                // Events are reordered within the reorderLatency
                PartitionedStreamEvent.CreatePoint(0, 20, 0),
                PartitionedStreamEvent.CreatePoint(0, 25, 0),
                PartitionedStreamEvent.CreatePoint(0, 30, 0),

                // Each partition acts independently
                PartitionedStreamEvent.CreatePoint(1, 1, 0),
                PartitionedStreamEvent.CreatePoint(1, 5, 0),
                PartitionedStreamEvent.CreatePoint(1, 10, 0),

                // Generated by the default OnCompletedPolicy EndOfStream
                PartitionedStreamEvent.CreateLowWatermark <int, int>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(expected);
        }
Ejemplo n.º 29
0
        // StartEdge-only streamables should never clean up partitions, since start edges are always valid state
        private void StartEdgeWorker <TPayload>(
            Func <IPartitionedIngressStreamable <int, TPayload>, IStreamable <PartitionKey <int>, double> > createQuery,
            Func <int, long, TPayload> resultCreator)
        {
            SetupQuery(createQuery, out var input);

            input.OnNext(CreateInputInterval(key: 1, startTime: 100, resultCreator));
            input.OnNext(CreateInputInterval(key: 2, startTime: 100, resultCreator));

            input.OnNext(CreateInputInterval(key: 1, startTime: 160, resultCreator));

            input.OnNext(CreateInputInterval(key: 1, startTime: 250, resultCreator));
            input.OnNext(CreateInputInterval(key: 2, startTime: 250, resultCreator));

            input.OnCompleted();

            var expected = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreateLowWatermark <int, double>(80),
                CreateOutputStart(key: 1, startTime: 100, average: 100),
                CreateOutputStart(key: 2, startTime: 100, average: 100),

                PartitionedStreamEvent.CreateLowWatermark <int, double>(140),
                CreateOutputEnd(key: 1, endTime: 160, originalStart: 100, average: 100),
                CreateOutputStart(key: 1, startTime: 160, average: 130),    // Average(100, 160)=130

                PartitionedStreamEvent.CreateLowWatermark <int, double>(230),
                CreateOutputEnd(key: 1, endTime: 250, originalStart: 160, average: 130),
                CreateOutputEnd(key: 2, endTime: 250, originalStart: 100, average: 100),
                CreateOutputStart(key: 1, startTime: 250, average: 170),    // Average(100, 160, 250)=170
                CreateOutputStart(key: 2, startTime: 250, average: 175),    // Average(100, 250)=175

                PartitionedStreamEvent.CreateLowWatermark <int, double>(StreamEvent.InfinitySyncTime),
            };

            FinishQuery(input, expected);
        }
Ejemplo n.º 30
0
        public void SelectManyWithFlush()
        {
            var data = new PartitionedStreamEvent <int, double>[]
            {
                PartitionedStreamEvent.CreatePoint(0, 0, 0.0),
                PartitionedStreamEvent.CreatePoint(0, 1, 1.0),
                PartitionedStreamEvent.CreatePoint(0, 2, 2.0),
                PartitionedStreamEvent.CreatePoint(1, 1, 1.0),
                PartitionedStreamEvent.CreatePoint(1, 2, 2.0),
                PartitionedStreamEvent.CreatePoint(1, 3, 3.0),
                PartitionedStreamEvent.CreatePoint(2, 2, 2.0),
                PartitionedStreamEvent.CreatePoint(2, 3, 3.0),
                PartitionedStreamEvent.CreatePoint(2, 4, 4.0),
            };

            var j   = new Subject <PartitionedStreamEvent <int, double> >();
            var res = new List <Notification <PartitionedStreamEvent <int, double> > >();

            var qc     = new QueryContainer();
            var input  = qc.RegisterInput(j);
            var output = qc.RegisterOutput(input.SelectMany(e => new[] { e, 100.0 * e }));

            using (j)
                using (output.Subscribe(res.NotificationListObserver()))
                {
                    Process p = qc.Restore(null);
                    foreach (var x in data)
                    {
                        j.OnNext(x);
                    }

                    p.Flush();
                    Assert.IsTrue(res.Count > data.Length, "Flush should push all events out.");

                    j.OnCompleted();
                }
        }