コード例 #1
0
        private async Task Wait(int timeout = 3000)
        {
            var sw            = Stopwatch.StartNew();
            var maxCheckpoint = await _fixture.EventStore.ReadHeadPosition(CancellationToken.None).ConfigureAwait(false);

            AllStreamPosition checkpoint = AllStreamPosition.None;

            while (sw.ElapsedMilliseconds < timeout)
            {
                if (_fixture.Observer.All.Any())
                {
                    // var name = _fixture.Observer.All.First().Key;
                    // var id = ProjectionPosition.GetIdFromName(name);
                    // using (var s = _fixture.SessionFactory())
                    // {
                    //     var cp = await s.LoadAsync<ProjectionPosition>(id).ConfigureAwait(false);
                    //     checkpoint = AllStreamPosition.FromNullableInt64(cp?.Position);
                    // }
                    if (_fixture.Observer.Min >= maxCheckpoint)
                    {
                        return;
                    }
                }
                await Task.Delay(300);
            }
            foreach (var state in _fixture.Observer.All.Values)
            {
                _writeLine($"[{state.Name}]: {state.Checkpoint} {state.Suspended} {state.Exception}");
            }
            throw new TimeoutException();
        }
コード例 #2
0
        private ReadAllPage Read(AllStreamPosition from)
        {
            var maxPosition = MaxPosition;

            _writeLine($"From {from}, Max {maxPosition}");
            if (from > MaxPosition)
            {
                var page = new ReadAllPage(from, from, true, new Envelope[0]);
                _writeLine(page.ToString());
                return(page);
            }
            var messages = Enumerable.Range(0, 10)
                           .Where(x => x <= maxPosition - from.ToInt64())
                           .Select(x => new Envelope(from.Shift(x), x))
                           .ToArray();
            bool isEnd  = !messages.Any() || messages.Last().Checkpoint.ToInt64() == maxPosition;
            var  result = new ReadAllPage(
                from,
                messages.Any() ? messages.Last().Checkpoint.Shift() : from,
                isEnd,
                messages);

            _writeLine(result.ToString());
            return(result);
        }
コード例 #3
0
        public async Task Notification_on_position_change()
        {
            // this also verifies cancellation
            (await Wait()).ShouldBeFalse();

            _currentPosition = _currentPosition.Shift();
            (await Wait()).ShouldBeTrue();
        }
コード例 #4
0
        public async Task Recovers_on_error()
        {
            _currentPosition = new AllStreamPosition(9998);
            (await Wait()).ShouldBeTrue();

            _currentPosition = _currentPosition.Shift();
            (await Wait()).ShouldBeFalse();
            (await _error.Task.ConfigureAwait(false)).ShouldBeOfType <InvalidOperationException>();

            _currentPosition = _currentPosition.Shift();
            (await Wait()).ShouldBeTrue();
        }
コード例 #5
0
 private Task <IDisposable> CreateSubscription(
     AllStreamPosition fromPosition,
     MessageReceived onMessage,
     HasCaughtUp hasCaughtUp,
     Func <Exception, Task> onSubscriptionError) =>
 Task.FromResult <IDisposable>(new GenericSubscription(
                                   (from, ct) => EventStore.ReadForward(from, cancellationToken: ct),
                                   fromPosition,
                                   Notifier.WaitForNotification,
                                   onMessage,
                                   onSubscriptionError,
                                   hasCaughtUp));
コード例 #6
0
 /// <summary>
 /// Subscribes to latest changes.
 /// Only supports a single subscriber at a time, based on notifier implementation.
 /// </summary>
 public Task <IDisposable> Subscribe(
     AllStreamPosition fromPosition,
     MessageReceived onMessage,
     HasCaughtUp hasCaughtUp,
     Func <Exception, Task> onSubscriptionError) =>
 Task.FromResult <IDisposable>(
     new GenericSubscription(
         (f, ct) => ReadForward(f, 10, ct),
         fromPosition,
         _notifier.WaitForNotification,
         onMessage,
         onSubscriptionError,
         hasCaughtUp));
コード例 #7
0
 public PollingNotifierTests()
 {
     _currentPosition = AllStreamPosition.None;
     _notifier        = new PollingNotifier(
         _ => _currentPosition.ToInt64() != 9999
             ? Task.FromResult(_currentPosition)
             : throw new InvalidOperationException("Error happened"),
         (ex, p) =>
     {
         _error.SetResult(ex);     // this actually fails 2nd+ time (intentional)
         return(Task.CompletedTask);
     },
         interval: Interval);
 }
コード例 #8
0
        public async Task Checkpoint_is_stored_on_commit()
        {
            var expected = new AllStreamPosition(10);

            using (var cpStore = Util.BuildCheckpointStore())
                using (var sut = new CheckpointProjection(new DelegateProjection(), cpStore))
                {
                    await sut.Project(new Envelope(expected, null));

                    await sut.Commit();

                    cpStore.Read().ShouldBe(expected.ToInt64());
                }
        }
コード例 #9
0
        public SubscriptionFixture(Action <string> writeLine,
                                   long maxPosition = 20,
                                   long handlerExceptionPosition = -2)
        {
            _writeLine  = writeLine;
            _cts        = new CancellationTokenSource();
            MaxPosition = maxPosition;
            AllStreamPosition hasCaughtUpTrigger = AllStreamPosition.None;
            AllStreamPosition notifierTrigger    = AllStreamPosition.None;
            ReadAllPageFunc   readAllPage        = (from, ct) => Task.FromResult(Read(from));
            MessageReceived   handler            = (s, m, ct) =>
            {
                LastProcessed = m.Checkpoint;
                if (m.Checkpoint == handlerExceptionPosition)
                {
                    throw new InvalidOperationException("Custom exception thrown");
                }
                return(Task.CompletedTask);
            };
            Func <Exception, Task> onError     = ex => Async(() => _exceptionSource.SetResult(ex));
            HasCaughtUp            hasCaughtUp = () => Async(() => hasCaughtUpTrigger = hasCaughtUpTrigger.Shift());

            var hasCaughtUpNotifier = new PollingNotifier(_ => Task.FromResult(hasCaughtUpTrigger));
            var notifier            = new PollingNotifier(_ => Task.FromResult(notifierTrigger));

            Subscription = new GenericSubscription(
                readAllPage,
                AllStreamPosition.None,
                notifier.WaitForNotification,
                handler,
                onError,
                hasCaughtUp);

            var cancellationToken = _cts.Token;

            cancellationToken.Register(() =>
            {
                Subscription.Dispose();
                notifier.Dispose();
                hasCaughtUpNotifier.Dispose();
            });

            WaitForCaughtUp = () => hasCaughtUpNotifier.WaitForNotification(cancellationToken);
            AppendEvents    = c =>
            {
                MaxPosition    += c;
                notifierTrigger = notifierTrigger.Shift();
            };
        }
コード例 #10
0
        public static async Task LoadCheckpoints(
            Func <IAsyncDocumentSession> sessionFactory,
            ProjectionGroupStateObserver observer,
            IEnumerable <string> keys)
        {
            using (var session = sessionFactory())
            {
                var docs = await session.LoadAsync <ProjectionPosition>(
                    keys.Select(ProjectionPosition.GetIdFromName)).ConfigureAwait(false);

                var pairs = keys.Zip(docs, (k, d) =>
                                     new KeyValuePair <string, AllStreamPosition>(k, AllStreamPosition.FromNullableInt64(d?.Position)));
                foreach (var pair in pairs)
                {
                    observer.MoveTo(pair.Key, pair.Value);
                }
            }
        }
コード例 #11
0
        public async Task Checkpoint_is_notified_but_not_stored_on_project()
        {
            var expected = new AllStreamPosition(10);

            AllStreamPosition projected = AllStreamPosition.None;
            AllStreamPosition notified  = AllStreamPosition.None;

            using (var cpStore = Util.BuildCheckpointStore())
                using (var sut = new CheckpointProjection(
                           Util.Projection(m => projected = m.Checkpoint),
                           cpStore,
                           p => notified = p))
                {
                    await sut.Project(new Envelope(expected, null));

                    projected.ShouldBe(expected);
                    notified.ShouldBe(expected);
                    cpStore.Read().ShouldBeNull();
                }
        }
コード例 #12
0
        private Task <IDisposable> CreateSubscription(
            AllStreamPosition fromPosition,
            MessageReceived onMessage,
            LocalProjections.HasCaughtUp hasCaughtUp,
            Func <Exception, Task> onSubscriptionError)
        {
            SqlStreamStore.Subscriptions.AllStreamMessageReceived receivedHandler = (s, m) =>
                                                                                    onMessage(s, new Envelope(new AllStreamPosition(m.Position), m), CancellationToken.None);
            SqlStreamStore.Subscriptions.AllSubscriptionDropped subscriptionDroppedHandler = (s, r, e) =>
                                                                                             (r != SubscriptionDroppedReason.Disposed ? onSubscriptionError(e) : Task.CompletedTask)
                                                                                             .GetAwaiter().GetResult();
            SqlStreamStore.Subscriptions.HasCaughtUp caughtUpHandler = caughtUp =>
                                                                       (caughtUp == true ? hasCaughtUp() : Task.CompletedTask).GetAwaiter().GetResult();

            var subscription = EventStore.SubscribeToAll(
                fromPosition.ToNullableInt64(),
                receivedHandler,
                subscriptionDroppedHandler,
                caughtUpHandler);

            return(Task.FromResult <IDisposable>(subscription));
        }
コード例 #13
0
        public Task <ReadAllPage> ReadForward(
            AllStreamPosition from = default(AllStreamPosition),
            int batchSize          = 10,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            var pairs = _allStream.ReadAfter(from.ToInt64() - 1, batchSize);

            var messages = pairs.Select(p => new Envelope(
                                            TranslateKey(p.Key),
                                            Serializer.DeserializeJson <DocumentSaved>(p.Value)))
                           .ToArray();

            if (messages.Length == 0)
            {
                return(Task.FromResult(new ReadAllPage(from, from, true, new Envelope[0])));
            }

            var next  = messages.Last().Checkpoint.Shift();
            var isEnd = _allStream.GetLastCheckpoint().Key < next;

            return(Task.FromResult(new ReadAllPage(from, next, isEnd, messages)));
        }
コード例 #14
0
        public async Task Only_first_messages_before_error_are_processed()
        {
            var expected = new AllStreamPosition(3);
            AllStreamPosition lastCheckpoint = AllStreamPosition.None;

            using (var sut = new SuspendableProjection(
                       Util.Projection(m =>
            {
                lastCheckpoint = m.Checkpoint;
                if (m.Checkpoint == expected)
                {
                    throw new Exception("test");
                }
            })))
            {
                for (int i = 1; i < 5; i++)
                {
                    await sut.Project(new Envelope(new AllStreamPosition(i), null));
                }
            }
            lastCheckpoint.ShouldBe(expected);
        }
コード例 #15
0
        public async Task Commit_happens_only_after_nth_attempt(int n)
        {
            AllStreamPosition projected = AllStreamPosition.None;
            bool committed = false;

            using (var sut = new CommitNthProjection(
                       Util.Projection(m => projected = m.Checkpoint, () => committed = true),
                       n))
            {
                for (int i = 0; i < n; i++)
                {
                    var expected = new AllStreamPosition(i);
                    await sut.Project(new Envelope(expected, null));

                    projected.ShouldBe(expected);
                    if (i < n - 1)
                    {
                        committed.ShouldBeFalse();
                    }
                }
            }
            committed.ShouldBeTrue();
        }
コード例 #16
0
ファイル: Envelope.cs プロジェクト: mihasic/LocalProjections
 public Envelope(AllStreamPosition checkpoint, object payload)
 {
     Checkpoint = checkpoint;
     Payload    = payload;
 }