/// <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);
            }
        }
示例#3
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;
            }
        }
示例#4
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);
        }
示例#5
0
        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);
            }
        }
示例#7
0
 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);
        }
示例#10
0
        public override Task NotAcknowledge(string?reason = null)
        {
            _eventStorePersistentSubscriptionBase?.Fail(ResolvedEvent, PersistentSubscriptionNakEventAction.Retry, reason);

            return(Task.CompletedTask);
        }