Example #1
0
        public async Task WithinPartition_by_range_correctly_partitions_queries_by_guid()
        {
            var id = Guid.NewGuid().ToString();

            await WriteEvents(i => new Event
            {
                SequenceNumber = i,
                Id             = id
            });

            var stream = Stream.PartitionedByRange <Event, int, Guid>(async(q, p) =>
            {
                using (var db = new AlluvialSqlTestsDbContext())
                {
                    return(await db.Events
                           .Where(e => e.Id == id)
                           .WithinPartition(e => e.Guid, p)
                           .ToArrayAsync());
                }
            });

            var catchup = stream.DistributeAmong(Partition.AllGuids().Among(20));

            var store = new InMemoryProjectionStore <int>();

            catchup.Subscribe(async(count, events) => events.Count, store);

            await catchup.RunSingleBatch();

            store.Sum(e => e).Should().Be(100);
        }
Example #2
0
        public async Task GuidQueryPartitioner_partitions_guids_fairly()
        {
            var totalNumberOfGuids = 1000;
            var numberOfPartitions = 50;

            var partitions = Partition.AllGuids()
                             .Among(numberOfPartitions);

            var guids = Enumerable.Range(1, totalNumberOfGuids).Select(_ => Guid.NewGuid()).ToArray();

            var partitioned = Stream.Partitioned <Guid, int, Guid>(
                async(q, p) =>
                guids.Where(g => g.IsWithinPartition(p)),
                advanceCursor: (q, b) => q.Cursor.AdvanceTo(totalNumberOfGuids));

            var aggregator = Aggregator.Create <Projection <HashSet <Guid>, int>, Guid>((p, b) =>
            {
                if (p.Value == null)
                {
                    p.Value = new HashSet <Guid>();
                }
                foreach (var guid in b)
                {
                    p.Value.Add(guid);
                }
            });
            var store = new InMemoryProjectionStore <Projection <HashSet <Guid>, int> >();

            await Task.WhenAll(partitions.Select(async partition =>
            {
                var stream = await partitioned.GetStream(partition);

                var catchup = StreamCatchup.Create(stream, batchSize: int.MaxValue);
                catchup.Subscribe(aggregator, store);
                await catchup.RunSingleBatch();

                var projection = await store.Get(stream.Id);
                Console.WriteLine(partition + ": " + projection.Value.Count);
            }));

            var approximateGuidsPerPartition = totalNumberOfGuids / numberOfPartitions;
            var tolerance = (int)(totalNumberOfGuids * .12);

            store.Sum(p => p.Value.Count).Should().Be(totalNumberOfGuids);

            store.ToList().ForEach(projection =>
            {
                projection.Value
                .Count
                .Should()
                .BeInRange(approximateGuidsPerPartition - tolerance,
                           approximateGuidsPerPartition + tolerance);
            });
        }
Example #3
0
        public async Task Guid_partitions_as_integers_are_gapless()
        {
            int numberOfPartitions = 1000;

            var partitions = Partition.AllGuids()
                             .Among(numberOfPartitions)
                             .ToArray();

            for (var i = 0; i < numberOfPartitions - 1; i++)
            {
                var firstPartition  = partitions[i];
                var secondPartition = partitions[i + 1];

                firstPartition.LowerBoundExclusive.Should().NotBe(firstPartition.UpperBoundInclusive);

                firstPartition.UpperBoundInclusive
                .Should()
                .Be(secondPartition.LowerBoundExclusive);

                firstPartition.UpperBoundInclusive.ToBigInteger()
                .Should()
                .Be(secondPartition.LowerBoundExclusive.ToBigInteger());
            }
        }