private async Task Subscribe(string productStream, string queryGroup) { try { await _connection.CreatePersistentSubscriptionAsync(productStream, queryGroup, PersistentSubscriptionSettings.Create().ResolveLinkTos().StartFromBeginning(), new UserCredentials(_eventStoreSettings.UserName, _eventStoreSettings.Password)); } catch (Exception e) { } async Task EventAppeared(EventStorePersistentSubscriptionBase s, ResolvedEvent e) { using (var scope = _serviceProvider.CreateScope()) { var mediator = scope.ServiceProvider.GetRequiredService <IMediator>(); var @event = JsonConvert.DeserializeObject(Encoding.UTF8.GetString(e.Event.Data), new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }) as INotification; await mediator.Publish(@event); } }; void SubscriptionDropped(EventStorePersistentSubscriptionBase e, SubscriptionDropReason s, Exception exc) { _subscriptions.TryTake(out e); _subscriptions.Add(_connection.ConnectToPersistentSubscriptionAsync(productStream, queryGroup, EventAppeared, SubscriptionDropped).Result); }; _subscriptions.Add(await _connection.ConnectToPersistentSubscriptionAsync(productStream, queryGroup, EventAppeared, SubscriptionDropped)); }
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; }
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 async Task Crate() { #region CreatePersistentSubscription var userCredentials = new UserCredentials("admin", "changeit"); var settings = PersistentSubscriptionSettings .Create() .DoNotResolveLinkTos() .StartFromCurrent(); await conn.CreatePersistentSubscriptionAsync( "myStream", "grour1", settings, userCredentials ); var subscription = await conn.ConnectToPersistentSubscriptionAsync( "myStream", "group1", (_, evt) => Console.WriteLine($"Received: {Encoding.UTF8.GetString(evt.Event.Data)}") ); #endregion CreatePersistentSubscription }
public async Task Subscribe(string streamName, Func <Guid, object, Task> messageSender) { await DefaultRetryAsync(() => SubscribeImpl()); async Task SubscribeImpl() { await CreateSubscription(); await _conn.ConnectToPersistentSubscriptionAsync( streamName, _options.GroupSubscription, (_, x) => messageSender( GetAggregateId(x.Event.EventStreamId), _eventDeserializer.Deserialize(x.Event))); Guid GetAggregateId(string streamId) { var streamIdParts = streamId.Split('-'); return(streamIdParts.Length == 2 ? Guid.TryParse(streamIdParts[1], out Guid aggregateId) ? aggregateId : Guid.Empty : Guid.Empty); } async Task CreateSubscription() { var settings = PersistentSubscriptionSettings.Create() .ResolveLinkTos() .StartFromCurrent(); await _conn.CreatePersistentSubscriptionAsync(streamName, _options.GroupSubscription, settings, _options.Credentials); } } }
//todo: handle ack private IObservable <IEvent> SubscribeToPersistentSubscription([NotNull] string streamId, [NotNull] string group) { return(Observable.Create <IEvent>(async(obs) => { var persistentSubscription = await _eventStoreConnection.ConnectToPersistentSubscriptionAsync(streamId, group, (eventStoreSubscription, resolvedEvent) => { var @event = DeserializeEvent(resolvedEvent.Event); @event.Version = resolvedEvent.Event.EventNumber; obs.OnNext(@event); }, (subscription, reason, exception) => { if (null != exception) { obs.OnError(exception); } else { obs.OnError(new Exception($"{reason}")); } }, _eventStoreRepositoryConfiguration.UserCredentials, _eventStoreRepositoryConfiguration.BufferSize, _eventStoreRepositoryConfiguration.AutoAck); return Disposable.Create(() => { persistentSubscription.Stop(_eventStoreRepositoryConfiguration.ConnectionClosedTimeout); }); })); }
public async Task Connect() { var streamName = $"$ce-{typeof(T).Name}"; EventStorePersistentSubscriptionBase = await _eventStoreConnection.ConnectToPersistentSubscriptionAsync( streamName, _groupName, EventAppeared, SubscriptionDropped ); }
private static async Task StartMultipleSubscriptions() { try { await _subscriptionConnection.CreatePersistentSubscriptionAsync( "$et-AccountCreated", "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("$et-AccountCreated", "InvoiceGeneration", AccountCreatedEventAppeared); }
public static void Method() { var userCredentials = new UserCredentials("admin", "changeit"); var settings = PersistentSubscriptionSettings.Create() .DoNotResolveLinkTos().StartFromCurrent(); conn.CreatePersistentSubscriptionAsync("newstream", "gr1", settings, userCredentials).Wait(); var subscription = conn.ConnectToPersistentSubscriptionAsync( "newstream", "gr1", (_, evt) => { Console.WriteLine("Received: " + Encoding.UTF8.GetString(evt.Event.Data)); }).Result; }
public async Task Subscribe(CancellationToken cancelToken) { var stream = $"{_endpoint}.{Assembly.GetEntryAssembly().GetName().Version}"; var group = $"{_endpoint}.{Assembly.GetEntryAssembly().GetName().Version}.sub"; Logger.Write(LogLevel.Info, () => $"Endpoint [{_endpoint}] connecting to subscription group [{stream}]"); try { var settings = PersistentSubscriptionSettings.Create() .StartFromBeginning() .WithReadBatchOf(_readsize) .WithMessageTimeoutOf(TimeSpan.FromSeconds(60)) .CheckPointAfter(TimeSpan.FromSeconds(10)) .ResolveLinkTos() .WithNamedConsumerStrategy(SystemConsumerStrategies.RoundRobin); await _connection.CreatePersistentSubscriptionAsync(stream, group, settings, _connection.Settings.DefaultUserCredentials).ConfigureAwait(false); } catch (InvalidOperationException) { } ThreadPool.QueueUserWorkItem(_ => { while (Bus.OnMessage == null || Bus.OnError == null) { Logger.Warn($"Could not find NSBs onMessage handler yet - if this persists there is a problem."); Thread.Sleep(1000); } // PushSettings will only exist AFTER finding OnMessage if (_concurrencyLimit == null) { _concurrencyLimit = new SemaphoreSlim(Bus.PushSettings.MaxConcurrency); } _subscription = _connection.ConnectToPersistentSubscriptionAsync(stream, group, EventProcessor(cancelToken), subscriptionDropped: (sub, reason, e) => { Logger.Write(LogLevel.Warn, () => $"Subscription dropped for reason: {reason}. Exception: {e?.Message ?? "UNKNOWN"}"); ProcessingLive = false; Dropped?.Invoke(reason.ToString(), e); }, bufferSize: _readsize * 10, autoAck: false).Result; ProcessingLive = true; }); }
public async Task Start() { await connection.ConnectAsync(); await connection.ConnectToPersistentSubscriptionAsync( eventStoreOptions.CurrentValue.StreamName, eventStoreOptions.CurrentValue.GroupName, ((_, message) => { var plainText = Encoding.ASCII.GetString(message.Event.Data); Console.WriteLine($"Received message of type: {message.Event.EventType}"); Console.WriteLine(plainText); using (var scope = serviceProvider.CreateScope()) { switch (message.Event.EventType) { case EventTypes.ToDoCreated: { var parsedEvent = JsonConvert.DeserializeObject <CreateToDoItem>(plainText); var dbContext = scope.ServiceProvider.GetService <ToDoListContext>(); dbContext.ToDoItems.Add(parsedEvent.ToDoItem); dbContext.SaveChanges(); break; } case EventTypes.ToDoDeleted: { var parsedEvent = JsonConvert.DeserializeObject <DeleteToDoItem>(plainText); var dbContext = scope.ServiceProvider.GetService <ToDoListContext>(); dbContext.ToDoItems.Remove(new ToDoItem { Id = parsedEvent.Id }); dbContext.SaveChanges(); break; } } } })); }
public async Task Subscribe(Type eventType, string subscription, Func <object, Task> eventHandler) { var eventTypeStream = $"$et-{eventType.Name}"; var settings = PersistentSubscriptionSettings.Create().ResolveLinkTos().StartFromCurrent(); _logger.LogDebug($"Subscribing to {eventTypeStream} with {_credentials.Username}:{_credentials.Password}"); await CreateSubscription(subscription, eventTypeStream, settings); await _conn.ConnectToPersistentSubscriptionAsync( eventTypeStream, subscription, (_, ev) => { _logger.LogDebug($"Event Apperead {ev.Event}"); eventHandler(_eventDeserializer.Deserialize(ev.Event)); }); }
/// <summary> /// Asynchronously subscribes to a persistent subscription(competing consumer) on event store /// </summary> /// <param name="target">The connection to subscribe to</param> /// <param name="groupName">The subscription group to connect to</param> /// <param name="stream">The stream to subscribe to</param> /// <param name="eventAppeared">An action invoked when a new event is received over the subscription</param> /// <param name="subscriptionDropped">An action invoked if the subscription is dropped</param> /// <param name="userCredentials">User credentials to use for the operation</param> /// <param name="bufferSize">The buffer size to use for the persistent subscription</param> /// <param name="autoAck">Whether the subscription should automatically acknowledge messages processed. /// If not set the receiver is required to explicitly acknowledge messages through the subscription.</param> /// <remarks>This will connect you to a persistent subscription group for a stream. The subscription group /// must first be created with CreatePersistentSubscriptionAsync many connections /// can connect to the same group and they will be treated as competing consumers within the group. /// If one connection dies work will be balanced across the rest of the consumers in the group. If /// you attempt to connect to a group that does not exist you will be given an exception. /// </remarks> /// <returns>An <see cref="EventStorePersistentSubscriptionBase"/> representing the subscription</returns> public static Task <EventStorePersistentSubscriptionBase> ConnectToPersistentSubscriptionAsync( this IEventStoreConnection target, string stream, string groupName, Action <EventStorePersistentSubscriptionBase, ResolvedEvent> eventAppeared, Action <EventStorePersistentSubscriptionBase, SubscriptionDropReason, Exception> subscriptionDropped = null, UserCredentials userCredentials = null, int bufferSize = 10, bool autoAck = true) => target.ConnectToPersistentSubscriptionAsync( stream, groupName, ToTask(eventAppeared), subscriptionDropped, userCredentials, bufferSize, autoAck );
private void SubscribeToStream(IEventStoreConnection connection) { if (_subscription != null) { _subscription.Stop(TimeSpan.FromDays(1)); _subscription = null; } try { CreateSubscription(connection); _subscription = connection.ConnectToPersistentSubscriptionAsync(_streamName, Group, EventAppeared, SubscriptionDropped).Result; } catch (Exception e) when (e is ConnectionClosedException || e is ObjectDisposedException || e.InnerException is ConnectionClosedException || e.InnerException is ObjectDisposedException) { SubscriptionDropped(null, SubscriptionDropReason.ConnectionClosed, e); } }
/// <summary> /// Connects to subscription. /// </summary> /// <param name="streamName">Name of the stream.</param> /// <param name="groupName">Name of the group.</param> /// <param name="subscriptionGroupId">The subscription group identifier.</param> /// <param name="bufferSize">Size of the buffer.</param> /// <returns></returns> public async Task ConnectToSubscription(String streamName, String groupName, Guid subscriptionGroupId, Int32 bufferSize) { Guard.ThrowIfNullOrEmpty(streamName, typeof(ArgumentNullException), "Stream Name cannot be null or empty when connecting to a Subscription"); Guard.ThrowIfNullOrEmpty(groupName, typeof(ArgumentNullException), "Group Name cannot be null or empty when connecting to a Subscription"); Guard.ThrowIfInvalidGUID(subscriptionGroupId, typeof(ArgumentNullException), "Subscription Group Id cannot be an empty GUID when connecting to a Subscription"); // Setup the Event Appeared delegate Action <EventStorePersistentSubscriptionBase, ResolvedEvent> eventAppeared = (subscription, resolvedEvent) => PersistentSubscriptionEventAppeared(subscription, resolvedEvent, subscriptionGroupId); // Setup the Subscription Droppped delegate Action <EventStorePersistentSubscriptionBase, SubscriptionDropReason, Exception> subscriptionDropped = (subscription, reason, ex) => PersistentSubscriptionDropped(streamName, groupName, reason, ex, subscriptionGroupId); IEventStoreConnection connection = null; try { // Get the connection connection = await this.GetEventStoreConnection(); // Now connect await this.Connection.ConnectToPersistentSubscriptionAsync(streamName, groupName, eventAppeared, subscriptionDropped, this.UserCredentials, 10, false); } catch (Exception ex) { // Check if the exception is because group doesnt exist if (ex.InnerException != null && ex.InnerException.Message == "Subscription not found") { // Create the missing Group await this.CreatePersistentSubscriptionFromBeginning(streamName, groupName); // Retry the connection await connection.ConnectToPersistentSubscriptionAsync(streamName, groupName, eventAppeared, subscriptionDropped, this.UserCredentials, 10, false); } else { // Some other exception has happened so just throw to caller throw; } } }
// Based on code found at https://codeopinion.com/event-store-persistent-subscriptions-demo/ private async Task ConnectToSubscription() { _logger.LogInformation($"Connecting to subscription at: {DateTimeOffset.Now}"); var bufferSize = 10; var autoAck = true; subscription = await conn.ConnectToPersistentSubscriptionAsync(streamName, groupName, (_, x) => { var data = Encoding.ASCII.GetString(x.Event.Data); Console.WriteLine($"Received: {x.Event.EventStreamId}:{x.Event.EventId}"); Console.WriteLine(data); }, (_, reason, ex) => { Console.WriteLine(ex); Console.WriteLine(reason); ConnectToSubscription().Wait(cancellationToken); }, userCredentials, bufferSize, autoAck); }
private void Subscribe(IEventStoreConnection connection) { connection.ConnectToPersistentSubscriptionAsync(Stream, Subscription, (_, x) => { try { Console.WriteLine($" process event : {x.Event.EventType}{x.Event.EventNumber} "); var evt = x.extract_data(); if (event_handlers.TryGetValue(evt.GetType(), out var handlers)) { Parallel.ForEach(handlers, handler => ((dynamic)handler).handle((dynamic)evt)); } } catch (Exception e) { Console.WriteLine($"Error process event: {x.Event.EventType}{x.Event.EventNumber} "); Console.WriteLine(e.StackTrace); } }); }
private void Subscribe(IEventStoreConnection connection) { connection.ConnectToPersistentSubscriptionAsync(Stream, Subscription, (_, x) => { try { Console.WriteLine($" process command : {x.Event.EventType}{x.Event.EventNumber} "); var command = x.extract_data(); if (command_handlers.TryGetValue(command.GetType(), out var handler)) { ((dynamic)handler).handler((dynamic)command); } _.Acknowledge(x.Event.EventId); } catch (Exception e) { Console.WriteLine($"Error process command: {x.Event.EventType}{x.Event.EventNumber} "); Console.WriteLine(e.StackTrace); } }, autoAck: false); }
public override async Task ConnectToPersistentSubscription( IAsyncStreamReader <ConnectToPersistentSubscriptionRequest> requestStream, IServerStreamWriter <ConnectToPersistentSubscriptionResponse> responseStream, ServerCallContext context) { Log.Debug("Waiting for subscription request..."); var success = await requestStream.MoveNext(); if (!success) { return; } Log.Debug("Subscription request received"); var request = requestStream.Current; Log.Debug("Starting subscription..."); var sub = await _eventStoreConnection.ConnectToPersistentSubscriptionAsync( request.Stream, request.GroupName, (subscription, @event) => { try { Log.Debug("Event appeared"); responseStream.WriteAsync(new ConnectToPersistentSubscriptionResponse { Event = new ResolvedEvent { Event = new RecordedEvent { Created = @event.OriginalEvent.Created.Ticks, CreatedEpoch = @event.OriginalEvent.CreatedEpoch, Data = ByteString.CopyFrom(@event.OriginalEvent.Data), EventId = ByteString.CopyFrom(@event.OriginalEvent.EventId.ToByteArray()), EventNumber = @event.OriginalEvent.EventNumber, EventStreamId = @event.OriginalEvent.EventStreamId, EventType = @event.OriginalEvent.EventType, IsJson = @event.OriginalEvent.IsJson, Metadata = ByteString.CopyFrom(@event.OriginalEvent.Metadata) }, Position = new Position { CommitPosition = @event.OriginalPosition.HasValue ? @event.OriginalPosition.Value.CommitPosition : 0, PreparePosition = @event.OriginalPosition.HasValue ? @event.OriginalPosition.Value.PreparePosition : 0 } } }) .Wait(); Log.Debug($"Event sent to subscriber {@event.OriginalEvent.EventNumber}"); } catch (InvalidOperationException e) { Log.Warn("Failed to send event to subscriber", e); throw; } }, (subscription, dropReason, ex) => { try { Log.Debug("Subscription dropped"); responseStream.WriteAsync(new ConnectToPersistentSubscriptionResponse { DropReason = dropReason.ToPersistentSubscriptionDropReason(), Error = ex == null ? null : new Error { Text = ex.Message, Type = ex.GetType().Name }, }) .Wait(); Log.Debug("Subscription drop sent to subscriber"); } catch (InvalidOperationException e) { Log.Warn("Failed to send drop reason to subscriber", e); } }, request.UserCredentials.ToUserCredentials()); Log.Debug("Subscription started"); Log.Debug("Waiting for subscription close..."); while (await requestStream.MoveNext()) { Log.Debug("Receiving another subscription request... ignoring"); } Log.Debug("Subscription closed"); Log.Debug("Stoping subscription..."); await Task.Run(() => { try { sub.Stop(TimeSpan.FromSeconds(10)); } catch (TimeoutException e) { Log.Error("Took too long to stop subscription", e); } }); Log.Debug("Subscription stopped"); }
private void ConnectToSubscription() { var sub = conn.ConnectToPersistentSubscriptionAsync(settings.Stream, settings.SubscriptionGroup, EventAppeared, SubscriptionDropped, User, settings.Buffersize, settings.AutoAck); }
static async Task Main(string[] args) { Console.WriteLine("Connecting to EventStore..."); IEventStoreConnection conn = await GetEventStoreConnection(); Console.WriteLine("Connected!"); //foreach (string f in Directory.GetFiles("../../../../sample-data/", "shoppingCart-*")) //{ // var streamName = Path.GetFileNameWithoutExtension(f); // var step3EventData = JsonConvert.DeserializeObject<List<EventDataWrapper>>(File.ReadAllText(f)).Select(x => x.ToEventData()); // var eventData = step3EventData.ToArray(); // await conn.AppendToStreamAsync(streamName, ExpectedVersion.Any, eventData); //} do { Console.Write("Want to write (w), read (r) or subscribe(s)? "); string option = Console.ReadLine(); if (option == "w") { Console.Write("value: "); string value = Console.ReadLine(); Console.WriteLine("Writting new event..."); await WriteEvent(conn, value); Console.WriteLine("Event written!"); } else if (option == "r") { //var readResult = await esConnection.ReadEventAsync("entity-1", 0, true); //Console.WriteLine(Encoding.UTF8.GetString(readResult.Event.Value.Event.Data)); var readEvents = await conn.ReadStreamEventsForwardAsync("entity-1", 0, 10, true); foreach (var evt in readEvents.Events) { Console.WriteLine(evt.Event.EventType + " - " + Encoding.UTF8.GetString(evt.Event.Data)); } } else { var settings = PersistentSubscriptionSettings.Create().DoNotResolveLinkTos().StartFromCurrent(); try { await conn.CreatePersistentSubscriptionAsync("entity-1", "gr1", settings, new UserCredentials("admin", "changeit")); } catch (Exception) { } EventStorePersistentSubscriptionBase subscription = await conn.ConnectToPersistentSubscriptionAsync( "entity-1", "gr1", (_, evt) => { Console.WriteLine("Received: " + Encoding.UTF8.GetString(evt.Event.Data)); }); Console.Clear(); Console.WriteLine("Listening to subscription..."); Console.ReadKey(); } Console.WriteLine("--------------------------"); Console.WriteLine(""); } while (true); }
private async Task Subscribe() { CreateSubscription(); await _subscriber.ConnectToPersistentSubscriptionAsync(_inputStream, _persistentSubscriptionGroup, EventAppeared, SubscriptionDropped); }
protected override IDisposable ConnectToEventStream(IEventStoreConnection connection) { void stopSubscription() { if (null != _eventStorePersistentSubscription) { _eventStorePersistentSubscription.Stop(TimeSpan.FromSeconds(5)); } } void onEvent(EventStorePersistentSubscriptionBase _, ResolvedEvent resolvedEvent) { Logger?.LogDebug($"{Id} => onEvent - {resolvedEvent.Event.EventId}"); OnResolvedEvent(resolvedEvent); } void onSubscriptionDropped(EventStorePersistentSubscriptionBase _, SubscriptionDropReason subscriptionDropReason, Exception exception) { switch (subscriptionDropReason) { case SubscriptionDropReason.UserInitiated: break; case SubscriptionDropReason.ConnectionClosed: case SubscriptionDropReason.NotAuthenticated: case SubscriptionDropReason.AccessDenied: case SubscriptionDropReason.SubscribingError: case SubscriptionDropReason.ServerError: case SubscriptionDropReason.CatchUpError: case SubscriptionDropReason.ProcessingQueueOverflow: case SubscriptionDropReason.EventHandlerException: case SubscriptionDropReason.MaxSubscribersReached: case SubscriptionDropReason.PersistentSubscriptionDeleted: case SubscriptionDropReason.Unknown: case SubscriptionDropReason.NotFound: default: Logger?.LogError(exception, $"{nameof(SubscriptionDropReason)}: [{subscriptionDropReason}] throwed the consumer in an invalid state"); if (_eventStoreStreamConfiguration.DoAppCrashOnFailure) { _killSwitch.KillProcess(exception); } else { createNewPersistentSubscription().Wait(); } break; } } async Task createNewPersistentSubscription() { stopSubscription(); Logger?.LogInformation($"{Id} => {nameof(PersistentSubscriptionEventStoreStream)} - StreamId: {_persistentEventStoreStreamConfiguration.StreamId} - GroupId: {_persistentEventStoreStreamConfiguration.GroupId}"); _eventStorePersistentSubscription = await connection.ConnectToPersistentSubscriptionAsync( _persistentEventStoreStreamConfiguration.StreamId, _persistentEventStoreStreamConfiguration.GroupId, eventAppeared : onEvent, subscriptionDropped : onSubscriptionDropped, userCredentials : _persistentEventStoreStreamConfiguration.UserCredentials, _persistentEventStoreStreamConfiguration.BufferSize, _persistentEventStoreStreamConfiguration.AutoAck); }; createNewPersistentSubscription().Wait(); return(Disposable.Create(() => { stopSubscription(); })); }