private void SubscriptionDropped(EventStorePersistentSubscriptionBase sub, SubscriptionDropReason reason, Exception ex)
        {
            Live = false;

            Logger.Write(LogLevel.Info, () => $"Disconnected from subscription.  Reason: {reason} Exception: {ex}");

            // Todo: is it possible to ACK an event from a reconnection?
            //if (_toAck.Any())
            //    throw new InvalidOperationException(
            //        $"Eventstore subscription dropped and we need to ACK {_toAck.Count} more events");


            // Need to clear ReadyEvents of events delivered but not processed before disconnect
            ResolvedEvent e;

            while (!_waitingEvents.IsEmpty)
            {
                Queued.Decrement(Id);
                QueuedEvents.Decrement(Id);
                _waitingEvents.TryDequeue(out e);
            }
            if (reason == SubscriptionDropReason.UserInitiated)
            {
                return;
            }

            // Task.Run(Connect, _token);
        }
示例#2
0
        private static async Task EventAppeared(EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase, ResolvedEvent resolvedEvent)
        {
            if (resolvedEvent.Event.EventNumber > 0 &&
                resolvedEvent.Event.EventNumber % 500 == 0)
            {
                var metaJsonData  = Encoding.UTF8.GetString(resolvedEvent.Event.Metadata);
                var eventMetaData = JsonConvert.DeserializeObject <DomainMetadata>(metaJsonData);

                if (eventMetaData.Schema != AccountSchema.SchemaName)
                {
                    return;
                }

                var account = await _repository.GetAccountById(Guid.Parse(eventMetaData.StreamId));

                await _eventStore.SaveSnapshot(new AccountEventStreamId(account.Id), new AccountSnapShot()
                {
                    Balance               = account.State.Balance,
                    AccountNumber         = account.State.AccountNumber,
                    StreamId              = account.Id,
                    SnapshotStreamVersion = account.StreamVersion
                });

                Console.WriteLine($"Account: {eventMetaData.StreamId}, balance: {account.State.Balance}");

                Console.WriteLine($"Event {resolvedEvent.Event.EventNumber}: {resolvedEvent.Event.EventId}");
            }
        }
示例#3
0
        protected override async Task Given()
        {
            await base.Given();

            await _conn.CreatePersistentSubscriptionAsync(_streamName, "secondgroup", _settings,
                                                          DefaultData.AdminCredentials);

            _sub3 = _conn.ConnectToPersistentSubscription(_streamName, "secondgroup",
                                                          (subscription, @event) => {
                Console.WriteLine();
                return(Task.CompletedTask);
            },
                                                          (subscription, reason, arg3) => Console.WriteLine(), DefaultData.AdminCredentials);
            _sub4 = _conn.ConnectToPersistentSubscription(_streamName, "secondgroup",
                                                          (subscription, @event) => {
                Console.WriteLine();
                return(Task.CompletedTask);
            },
                                                          (subscription, reason, arg3) => Console.WriteLine(),
                                                          DefaultData.AdminCredentials);
            _sub5 = _conn.ConnectToPersistentSubscription(_streamName, "secondgroup",
                                                          (subscription, @event) => {
                Console.WriteLine();
                return(Task.CompletedTask);
            },
                                                          (subscription, reason, arg3) => Console.WriteLine(),
                                                          DefaultData.AdminCredentials);
        }
        protected override async Task OnInitializedAsync()
        {
            await base.OnInitializedAsync();

            Counters.Clear();

            var subSettings = PersistentSubscriptionSettings.Create()
                              .ResolveLinkTos()
                              .StartFromBeginning()
                              .Build();

            try {
                await Connection.CreatePersistentSubscriptionAsync(_subscriptionStream,
                                                                   _channel,
                                                                   subSettings,
                                                                   default);
            } catch (Exception) {
                await Connection.UpdatePersistentSubscriptionAsync(_subscriptionStream,
                                                                   _channel,
                                                                   subSettings,
                                                                   default);
            }

            _subscription = await Connection.ConnectToPersistentSubscriptionAsync(
                stream : _subscriptionStream,
                groupName : _channel,
                eventAppeared : async(sub, e, position) => {
                s_log.Information("Received counter-click.");
                await InvokeAsync(() => {
                    switch (e.Event.EventType)
                    {
                    case "counter-added":
                        var added = JsonSerializer.Deserialize <AddCounter>(new ReadOnlySpan <byte>(e.Event.Data));

                        Counters.Add(new Counter {
                            CounterId      = added.Id,
                            Label          = added.Label,
                            NumberOfClicks = 0
                        });

                        s_log.Information("Counter added.");
                        break;

                    case "counter-clicked":
                        var clickedOn = JsonSerializer.Deserialize <CounterClicked>(new ReadOnlySpan <byte>(e.Event.Data));
                        var counter   = Counters.SingleOrDefault(c => c.CounterId == clickedOn.CounterId);
                        if (counter != null)
                        {
                            s_log.Information("Counter entry found.  Adding +1 to value.");
                            counter.NumberOfClicks += 1;
                        }
                        s_log.Information("Counter clicked.");
                        break;
                    }

                    StateHasChanged();
                });
            },
                subscriptionDropped : (sub, reason, exc) => { },
                userCredentials : default
示例#5
0
        private async Task EventAppeared(EventStorePersistentSubscriptionBase sub, ResolvedEvent e, CancellationToken token,
                                         Func <string, long, IFullEvent, Task> callback)
        {
            // Don't care about metadata streams
            if (e.Event == null || e.Event.EventStreamId[0] == '$')
            {
                sub.Acknowledge(e.OriginalEvent.EventId);
                return;
            }

            if (token.IsCancellationRequested)
            {
                Logger.WarnEvent("Cancelation", "Token cancel requested");
                ThreadPool.QueueUserWorkItem((_) => sub.Stop(TimeSpan.FromSeconds(10)));
                token.ThrowIfCancellationRequested();
            }

            var eventId = $"{e.Event.EventId}:{e.Event.EventStreamId}:{e.Event.EventNumber}";

            _outstandingEvents[eventId] = new Tuple <EventStorePersistentSubscriptionBase, Guid>(sub, e.OriginalEvent.EventId);

            try
            {
                await EventAppeared(e, token, callback).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger.ErrorEvent("AppearedException", ex, "Stream: [{Stream:l}] Position: {StreamPosition} {ExceptionType} - {ExceptionMessage}", e.Event.EventStreamId, e.Event.EventNumber, ex.GetType().Name, ex.Message);
                sub.Fail(e, PersistentSubscriptionNakEventAction.Park, ex.GetType().Name);
                // don't throw, stops subscription and causes reconnect
                //throw;
            }
        }
示例#6
0
        private static async Task AccountCreatedEventAppeared(
            EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase, ResolvedEvent resolvedEvent)
        {
            var accountEvent = ConvertEventDataToAccountDomainEvent(resolvedEvent);

            if (accountEvent == null)
            {
                return;
            }

            try
            {
                await _subscriptionConnection.CreatePersistentSubscriptionAsync(
                    $"Account-{accountEvent.StreamId}",
                    "InvoiceGeneration",
                    PersistentSubscriptionSettings
                    .Create()
                    .StartFromBeginning()
                    .CheckPointAfter(TimeSpan.FromSeconds(5))
                    .ResolveLinkTos()
                    .Build(), new UserCredentials("admin", "changeit"));
            }
            catch (Exception e)
            {
                Console.WriteLine($"Subscription already exist.");
            }

            await _subscriptionConnection.ConnectToPersistentSubscriptionAsync($"Account-{accountEvent.StreamId}", "InvoiceGeneration", AccountEventAppeared);
        }
示例#7
0
        private Task EventAppeared(EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase,
                                   ResolvedEvent resolvedEvent)
        {
            try
            {
                if (resolvedEvent.OriginalEvent.EventType.StartsWith("$$"))
                {
                    return(Task.CompletedTask);
                }
                var data = DeserializeObject <CloudEventRequest>(resolvedEvent.OriginalEvent.Data);
                if (data == null)
                {
                    return(Task.CompletedTask);
                }
                foreach (var handler in _handlers)
                {
                    handler(data, CancellationToken.None);
                }
            }
            catch (Exception ex)
            {
                // any specific log must be catch before this point
                Log.Error($"Error while processing: '{ex.GetBaseException().Message}' StackTrace: {ex.StackTrace}");
                eventStorePersistentSubscriptionBase.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Park,
                                                          ex.GetBaseException().Message);
            }

            return(Task.CompletedTask);
        }
示例#8
0
        private async Task Connect()
        {
            _connection = _connectionProvider.GetConnection();
            await _connection.ConnectAsync();

            var streamId = _streamId == null ? $"$ce-{_aggregateType.ToUpper()}" : _streamId.Id;
            //Check if this subscription already exists
            await _connection.CreateSubscription(streamId,
                                                 _subscriptionName,
                                                 await _connectionProvider.GetCredentials(),
                                                 _logger);


            Func <EventStorePersistentSubscriptionBase, ResolvedEvent, int?, Task> processEvent = (subscriptionBase, resolvedEvent, c) => {
                return(HandleEvent(subscriptionBase, resolvedEvent));
            };

            _subscriptionBase = await _connection.ConnectToPersistentSubscriptionAsync(
                streamId,
                _subscriptionName,
                processEvent,
                bufferSize : 10,
                subscriptionDropped : SubscriptionDropped,
                autoAck : false);

            _connected = true;
            _status    = SubscriptionConnectionStatus.Connected;
        }
示例#9
0
 private void Dropped(EventStorePersistentSubscriptionBase sub, SubscriptionDropReason reason,
                      Exception exception)
 {
     _exception = exception;
     _reason    = reason;
     _resetEvent.Set();
 }
示例#10
0
 //Need to wait for this event and somehow notify the main task of its arrival maybe with a flag? Look for better options
 private static void EventAppeared(EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase,
                                   ResolvedEvent resolvedEvent)
 {
     var data = Encoding.ASCII.GetString(resolvedEvent.Event.Data);
     //Console.WriteLine("Received: " + resolvedEvent.Event.EventStreamId + ":" + resolvedEvent.Event.EventNumber);
     //Console.WriteLine(data);
 }
        private static void EventAppeared(EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase, ResolvedEvent resolvedEvent)
        {
            var x = resolvedEvent;

            Console.WriteLine($"{x.Event.Created.ToString("HH:mm:ss.ffff")} #{x.Event.EventNumber} -> {x.Event.EventType}' StreamID '{x.Event.EventStreamId}");

            var dataJSON = Encoding.ASCII.GetString(x.Event.Data);
            var metaJSON = Encoding.ASCII.GetString(x.Event.Metadata);

            //this needs to be a write domain deserialise
            Console.WriteLine("");
            Console.WriteLine($"EventType = {x.Event.EventType}");

            Console.WriteLine("");
            Console.WriteLine("DATA");
            Console.WriteLine(dataJSON);

            Console.WriteLine("");
            Console.WriteLine("META");
            Console.WriteLine(metaJSON);

            switch (x.Event.EventType)
            {
            case var exp when(exp.Contains("EventModel")):

                dynamic metaData = JsonConvert.DeserializeObject(metaJSON);

                var eventModel = JsonConvert.DeserializeObject <EventModel>(metaJSON);

                break;

            default:
                break;
            }
        }
        async Task ExecutePipeline(EventStorePersistentSubscriptionBase s, ResolvedEvent evnt, MessageContext pushContext, CancellationTokenSource tokenSource)
        {
            var errorHandleResult = ErrorHandleResult.RetryRequired;
            var failures          = 0;

            while (errorHandleResult != ErrorHandleResult.Handled)
            {
                try
                {
                    await pipeline(pushContext);

                    errorHandleResult = ErrorHandleResult.Handled;
                }
                catch (Exception ex)
                {
                    failures++;
                    errorHandleResult = await onError(ToErrorContext(evnt, ex, pushContext.TransportTransaction, failures));
                }
            }
            if (tokenSource.IsCancellationRequested)
            {
                s.Fail(evnt, PersistentSubscriptionNakEventAction.Retry, "User requested");
            }
            else
            {
                s.Acknowledge(evnt);
            }
        }
示例#13
0
        public async Task Connect()
        {
            Logger.Write(LogLevel.Info,
                         () => $"Connecting to subscription group [{_group}] on client {_client.Settings.GossipSeeds[0].EndPoint.Address}");
            // Todo: play with buffer size?

            while (!Live)
            {
                await Task.Delay(500, _token).ConfigureAwait(false);

                try
                {
                    _subscription = await _client.ConnectToPersistentSubscriptionAsync(_stream, _group,
                                                                                       eventAppeared : EventAppeared,
                                                                                       subscriptionDropped : SubscriptionDropped,
                                                                                       // Let us accept maxDelayed number of unacknowledged events
                                                                                       bufferSize : _maxDelayed,
                                                                                       autoAck : false).ConfigureAwait(false);

                    Live = true;
                    Logger.Write(LogLevel.Info,
                                 () => $"Connected to subscription group [{_group}] on client {_client.Settings.GossipSeeds[0].EndPoint.Address}");
                }
                catch (OperationTimedOutException) { }
            }
        }
 public void Connect()
 {
     _eventStoreConnection.ConnectAsync().Wait();
     CreatePersistentSubscription(_eventStoreConnection);
     EventStorePersistentSubscriptionBase = _eventStoreConnection.ConnectToPersistentSubscription(StreamName,
                                                                                                  GroupName, EventAppeared, SubscriptionDropped, _userCredentials);
 }
示例#15
0
            private void ConnectToSubscription()
            {
                var bufferSize = 10;
                var autoAck    = true;

                _subscription = _conn.ConnectToPersistentSubscription(STREAM, GROUP, EventAppeared, SubscriptionDropped,
                                                                      User, bufferSize, autoAck);
            }
示例#16
0
        public void ConnectToSubscription()
        {
            var bufferSize = 10;
            var autoAck    = true;

            _subscription = _conn.ConnectToPersistentSubscription(_stream, _group, EventAppeared, SubscriptionDropped,
                                                                  User, bufferSize, autoAck);
        }
 protected override void When()
 {
     _conn.CreatePersistentSubscriptionAsync(_stream, "agroupname17", _settings, DefaultData.AdminCredentials).Wait();
     _sub = _conn.ConnectToPersistentSubscription(_stream,
                                                  "agroupname17",
                                                  (sub, e) => Console.Write("appeared"),
                                                  (sub, reason, ex) => {});
 }
示例#18
0
        private void EventAppeared(EventStorePersistentSubscriptionBase sub, ResolvedEvent e)
        {
            _token.ThrowIfCancellationRequested();

            Logger.Write(LogLevel.Debug,
                         () => $"Delayed event appeared {e.Event.EventId} type {e.Event.EventType} stream [{e.Event.EventStreamId}] number {e.Event.EventNumber} projection event number {e.OriginalEventNumber}");
            Queued.Increment(Id);
            lock (_lock) _waitingEvents.Add(e);
        }
 private void HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent)
 {
     if (!_set)
     {
         _set        = true;
         _firstEvent = resolvedEvent;
         _resetEvent.Set();
     }
 }
        public async Task persistent_subscription_delivers_all_events(int iteration)
        {
            const int eventCount  = 250;
            const int totalEvents = eventCount * 2;
            EventStorePersistentSubscriptionBase subscription = null;

            try {
                var userCredentials = new UserCredentials("admin", "changeit");

                int hitCount = 0;

                var streamName       = $"stream_{iteration}";
                var subscriptionName = $"subscription_{iteration}";

                var completed = new AutoResetEvent(false);

                var connection = _fixture.Connection;

                for (var i = 0; i < eventCount; i++)
                {
                    await connection.AppendToStreamAsync(streamName, ExpectedVersion.Any, _fixture.CreateTestEvents())
                    .WithTimeout();
                }

                var builder = PersistentSubscriptionSettings.Create()
                              .StartFromBeginning()
                              .ResolveLinkTos();

                await connection.CreatePersistentSubscriptionAsync(streamName,
                                                                   subscriptionName,
                                                                   builder.Build(),
                                                                   userCredentials).WithTimeout();

                subscription = await connection.ConnectToPersistentSubscriptionAsync(streamName, subscriptionName,
                                                                                     (_, resolvedEvent) => {
                    var result = Interlocked.Increment(ref hitCount);
                    _.Acknowledge(resolvedEvent);

                    if (totalEvents == result)
                    {
                        completed.Set();
                    }
                });

                for (var i = 0; i < eventCount; i++)
                {
                    await connection.AppendToStreamAsync(streamName, ExpectedVersion.Any, _fixture.CreateTestEvents())
                    .WithTimeout();
                }

                completed.WaitOne(TimeSpan.FromSeconds(30));
                Assert.Equal(totalEvents, hitCount);
            } finally {
                subscription?.Stop(TimeSpan.FromSeconds(5));
            }
        }
示例#21
0
        private void ConnectToSubscription()
        {
            var bufferSize = 10;
            var autoAck    = true;

            _subscription = _conn.ConnectToPersistentSubscription(STREAM, GROUP,
                                                                  (Action <EventStorePersistentSubscriptionBase, ResolvedEvent>)EventAppeared,
                                                                  SubscriptionDropped,
                                                                  User, bufferSize, autoAck);
        }
 private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent)
 {
     if (!_set)
     {
         _set        = true;
         _firstEvent = resolvedEvent;
         _resetEvent.Set();
     }
     return(Task.CompletedTask);
 }
        private async void SubscriptionDropped(EventStorePersistentSubscriptionBase sub, SubscriptionDropReason reason, Exception ex)
        {
            _logger.LogError(ex, "PersistentSubscription Dropped on StreamId {StreamId}, Reason: {Reason}", sub, reason.ToString());

            if (!_cancellationToken.IsCancellationRequested)
            {
                _logger.LogInformation("Re Subscribe PersistentSubscription ");
                await ConnectToPersistentSubscriptionInternal().ConfigureAwait(false);
            }
        }
示例#24
0
        public void Connect()
        {
            var streamName = $"$ce-{typeof(T).Name}";

            EventStorePersistentSubscriptionBase = _eventStoreConnection.ConnectToPersistentSubscription(
                streamName,
                _groupName,
                EventAppeared,
                SubscriptionDropped
                );
        }
        public async Task Connect()
        {
            var streamName = $"$ce-{typeof(T).Name}";

            EventStorePersistentSubscriptionBase = await _eventStoreConnection.ConnectToPersistentSubscriptionAsync(
                streamName,
                _groupName,
                EventAppeared,
                SubscriptionDropped
                );
        }
示例#26
0
        private static Task OnNewEvent(EventStorePersistentSubscriptionBase arg1, ResolvedEvent arg2, int?arg3)
        {
            var json     = System.Text.Encoding.UTF8.GetString(arg2.Event.Data);
            var activity = JsonSerializer.Deserialize <Activity>(json, new JsonSerializerOptions
            {
                PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
                WriteIndented        = true
            });

            Console.WriteLine($"Activity received " + activity.Name + " " + activity.Other);
            return(Task.CompletedTask);
        }
示例#27
0
        private Task EventAppeared(EventStorePersistentSubscriptionBase subscription, ResolvedEvent resolvedEvent)
        {
            _telemetryClient.TrackEvent("New event appeared from EventStore (read model)", new Dictionary <string, string> {
                { "Type", resolvedEvent.Event.EventType },
                { "EventNumber", resolvedEvent.Event.EventNumber.ToString() },
                { "Created (Epoch)", resolvedEvent.Event.CreatedEpoch.ToString() }
            });

            var @event = _mapper.Map <IEvent>(resolvedEvent);

            return(_mediator.Publish(@event));
        }
        private void ConnectToSubscription()
        {
            var bufferSize = 10;
            var autoAck    = true;

            Console.WriteLine("**** Connecting to subscription ...");

            _subscription = _conn.ConnectToPersistentSubscription(STREAM, GROUP,
                                                                  (_base, _event) => { EventAppeared(_base, _event); },
                                                                  (_base, _reason, _exception) => { SubscriptionDropped(_base, _reason, _exception); },
                                                                  User, bufferSize, autoAck);
        }
示例#29
0
        private void EventAppeared(EventStorePersistentSubscriptionBase eventStorePersistentSubscriptionBase, ResolvedEvent resolvedEvent)
        {
            Console.WriteLine(eventStorePersistentSubscriptionBase.GetHashCode());
            EventCount++;
            Interlocked.Increment(ref Total);

            //if (Total % 10000 == 0)
            Console.WriteLine($"Persistant: Event from Stream {resolvedEvent.Event.EventStreamId} processed, Total: {Total}, {DateTime.Now}");
            //Encoding.ASCII.GetString(x.Event.Data)
            
            _checkpoint = resolvedEvent.Event.EventNumber;
        }
示例#30
0
 protected override void Given()
 {
     base.Given();
     _conn.CreatePersistentSubscriptionAsync(_stream, _group, _settings,
                                             DefaultData.AdminCredentials).Wait();
     // First connection
     _firstConn = _conn.ConnectToPersistentSubscriptionAsync(
         _stream,
         _group,
         (s, e) => s.Acknowledge(e),
         (sub, reason, ex) => { },
         DefaultData.AdminCredentials).Result;
 }