/// <summary> /// Persistents the subscription event appeared. /// </summary> /// <param name="subscription">The subscription.</param> /// <param name="resolvedEvent">The resolved event.</param> /// <param name="subscriptionGroupId">The subscription group identifier.</param> /// <returns></returns> private async Task PersistentSubscriptionEventAppeared(EventStorePersistentSubscriptionBase subscription, ResolvedEvent resolvedEvent, Guid subscriptionGroupId) { try { // Check the event data has been received if (this.EventAppeared != null) { // Serialise the event data //String serialisedData = this.Serialiser.Serialise(resolvedEvent); // Get the event data from the resolved Event var serialisedData = Encoding.UTF8.GetString(resolvedEvent.Event.Data); SubscriptionDataTransferObject subscriptionInformation = new SubscriptionDataTransferObject() { SerialisedData = serialisedData, EventId = (Guid)((RecordedEvent)resolvedEvent.Event).EventId, SubscriptionGroupId = subscriptionGroupId.ToString(), }; var handledSuccessfully = await this.EventAppeared(subscriptionInformation); if (!handledSuccessfully) { throw new Exception( $"Failed to Process Event {resolvedEvent.Event.EventId} on persistent subscription group {subscriptionGroupId}"); } } else { Logger.LogInformation("Unable to process event as EventAppeared Event handler is null"); } // Acknowledge the event subscription.Acknowledge(resolvedEvent); } catch (TimeoutException tex) { subscription.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Park, tex.Message); } catch (InvalidOperationException ioex) { subscription.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Skip, ioex.Message); } catch (Exception ex) { subscription.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Retry, ex.Message); } }
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); } }
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 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); }
public void Nack(ResolvedEvent[] events) { while (!Live) { Thread.Sleep(10); } _subscription.Fail(events, PersistentSubscriptionNakEventAction.Retry, "Failed to process"); }
private static async Task PushEventToProcessManager(AppFunc chain, IManageProcess processManager, DeSerializationResult evnt, IDictionary <string, object> environment, EventStorePersistentSubscriptionBase subscription) { if (!running) { return; } if (!evnt.Successful) { subscription.Fail(evnt.OriginalEvent, PersistentSubscriptionNakEventAction.Unknown, evnt.Error.Message); return; } try { var requestEnvironment = new Dictionary <string, object>(); foreach (var item in environment) { requestEnvironment[item.Key] = item.Value; } var request = requestEnvironment.GetEventStoreRequest(); request.ProcessManager = processManager; request.Event = evnt; var correlationId = evnt.Metadata.Get(DefaultRepository.CorrelationIdKey, Guid.NewGuid().ToString()); using (requestEnvironment.OpenCorrelationContext(correlationId)) using (requestEnvironment.OpenCausationContext(evnt.EventId.ToString())) { await chain(requestEnvironment).ConfigureAwait(false); } subscription.Acknowledge(evnt.OriginalEvent); } catch (Exception ex) { environment.Log(ex, "Couldn't push event to processmanager: {0}", LogLevel.Error, processManager.ProcessName); subscription.Fail(evnt.OriginalEvent, PersistentSubscriptionNakEventAction.Unknown, ex.Message); } }
private Task HandleEvent(EventStorePersistentSubscriptionBase sub, ResolvedEvent resolvedEvent, int?retryCount) { if (retryCount > 4) { _retryCount = retryCount; sub.Acknowledge(resolvedEvent); _resetEvent.Set(); } else { sub.Fail(resolvedEvent, PersistentSubscriptionNakEventAction.Retry, "Not yet tried enough times"); } return(Task.CompletedTask); }
private void DoSomething(EventStorePersistentSubscriptionBase _, ResolvedEvent x) { var data = Encoding.ASCII.GetString(x.Event.Data); try { Console.WriteLine(data); var pictureInfo = JsonConvert.DeserializeObject <PictureInfo>(data); AddToDB(pictureInfo); _.Acknowledge(x); }catch (Exception ex) { Console.Write(ex); _.Fail(x, PersistentSubscriptionNakEventAction.Park, ex.Message); } }
void OnEvent(EventStorePersistentSubscriptionBase s, ResolvedEvent evnt) { concurrencyLimiter.Wait(cancellationToken); var tokenSource = new CancellationTokenSource(); var pushContext = ToMessageContext(evnt, tokenSource); if (pushContext == null) //system message { return; } var receiveTask = Task.Run(() => { try { ExecutePipeline(s, evnt, pushContext, tokenSource).GetAwaiter().GetResult(); receiveCircuitBreaker.Success(); } catch (Exception ex) { s.Fail(evnt, PersistentSubscriptionNakEventAction.Retry, "Unhandled exception"); receiveCircuitBreaker.Failure(ex).GetAwaiter().GetResult(); } finally { concurrencyLimiter.Release(); } }, tokenSource.Token).ContinueWith(t => tokenSource.Dispose()); runningReceiveTasks.TryAdd(receiveTask, receiveTask); // We insert the original task into the runningReceiveTasks because we want to await the completion // of the running receives. ExecuteSynchronously is a request to execute the continuation as part of // the transition of the antecedents completion phase. This means in most of the cases the continuation // will be executed during this transition and the antecedent task goes into the completion state only // after the continuation is executed. This is not always the case. When the TPL thread handling the // antecedent task is aborted the continuation will be scheduled. But in this case we don't need to await // the continuation to complete because only really care about the receive operations. The final operation // when shutting down is a clear of the running tasks anyway. receiveTask.ContinueWith(t => { Task toBeRemoved; runningReceiveTasks.TryRemove(t, out toBeRemoved); }, TaskContinuationOptions.ExecuteSynchronously); }
public override Task NotAcknowledge(string?reason = null) { _eventStorePersistentSubscriptionBase?.Fail(ResolvedEvent, PersistentSubscriptionNakEventAction.Retry, reason); return(Task.CompletedTask); }