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); }
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}"); } }
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
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; } }
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); }
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); }
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; }
private void Dropped(EventStorePersistentSubscriptionBase sub, SubscriptionDropReason reason, Exception exception) { _exception = exception; _reason = reason; _resetEvent.Set(); }
//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); } }
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); }
private void ConnectToSubscription() { var bufferSize = 10; var autoAck = true; _subscription = _conn.ConnectToPersistentSubscription(STREAM, GROUP, EventAppeared, SubscriptionDropped, User, bufferSize, autoAck); }
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) => {}); }
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)); } }
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); } }
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 ); }
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); }
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); }
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; }
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; }