public async Task One_stream_can_transparently_delegate_to_another()
        {
            var upstream = NEventStoreStream.AllEvents(store);

            store.WriteEvents(i => new AccountOpened(), 100);
            var projection = new Projection <int, string>();

            var dependentStream = Stream.Create <int, string>(
                async q =>
            {
                var mapped = upstream.Map(e => new[] { e.Count() });
                var batch  = await mapped.Fetch(q);
                return(batch);
            });

            var catchup = StreamCatchup.Create(dependentStream, batchSize: 50);

            FetchAndSaveProjection <Projection <int, string> > manageProjection = async(id, aggregate) =>
            {
                await aggregate(projection);
            };

            catchup.Subscribe(async(p, b) =>
            {
                p.Value += b.Sum();
                return(p);
            }, manageProjection);

            await catchup.RunSingleBatch();

            Console.WriteLine(projection.ToLogString());

            projection.Value.Should().Be(50);
            projection.CursorPosition.Should().Be("50");
        }
        public async Task One_stream_can_use_anothers_cursor_to_limit_how_far_ahead_it_looks()
        {
            var aggregateId = Guid.NewGuid().ToString();

            Console.WriteLine(new { aggregateId });
            var upstream = NEventStoreStream.AggregateIds(store);

            store.WriteEvents(i => new AccountOpened
            {
                AggregateId = aggregateId
            }, 50);

            var streamPerAggregate = upstream.IntoMany(
                async(streamId, fromCursor, toCursor) =>
            {
                var stream = NEventStoreStream.AllEvents(store);

                var cursor = Cursor.New(fromCursor);
                var events = await stream.CreateQuery(cursor, int.Parse(toCursor)).NextBatch();

                var s = events.Select(e => e.Body)
                        .Cast <IDomainEvent>()
                        .GroupBy(e => e.AggregateId)
                        .Select(group => @group.AsStream(cursorPosition: i => i.CheckpointToken));

                return(s);
            });

            var streams = await streamPerAggregate.CreateQuery(batchSize : 25).NextBatch();

            var count = 0;

            foreach (var stream in streams.SelectMany(s => s))
            {
                count++;
                var batch = await stream.CreateQuery().NextBatch();

                batch.Count.Should().Be(25);
            }
        }
        public IStream <IStream <IDomainEvent, int>, string> StreamPerAggregate()
        {
            return(StreamUpdates()
                   .IntoMany(
                       async(streamUpdate, fromCursor, toCursor) =>
            {
                var allEvents = NEventStoreStream.AllEvents(store);

                var cursor = Cursor.New(fromCursor);
                var batch = await allEvents.CreateQuery(cursor, int.Parse(toCursor))
                            .NextBatch();

                var aggregate = batch.Select(e => e.Body)
                                .Cast <IDomainEvent>()
                                .Where(e => e.AggregateId == streamUpdate.StreamId);

                IStream <IDomainEvent, int> stream = aggregate.AsStream(
                    id: streamUpdate.StreamId,
                    cursorPosition: e => e.StreamRevision);

                return stream;
            }));
        }