Ejemplo n.º 1
0
 public object MutateIncoming(object Event, IEventDescriptor Descriptor, long?Position)
 {
     this.CurrentDescriptor = Descriptor;
     this.CurrentEvent      = Event;
     this.CurrentPosition   = Position;
     return(Event);
 }
Ejemplo n.º 2
0
        public void Publish(IEventDescriptor info)
        {
            var allListeners = this.eventListenerFinder.CreateAllEventListeners();

            allListeners = this.SortEventListeners(allListeners);
            foreach (var listener in allListeners)
            {
                var methodInfos = this.GetExecutableMethods(listener, info);

                foreach (var method in methodInfos)
                {
                    var ps = method.GetParameters();
                    if (ps.Length == 0)
                    {
                        method.Invoke(listener, new object[] { });
                        continue;
                    }

                    if (ps.Length == 1)
                    {
                        object inputObject = this.mapper.Convert(info.EventData, ps[0].ParameterType);
                        method.Invoke(listener, new object[] { inputObject });
                        continue;
                    }
                }
            }
        }
        public static IDictionary <String, String> ToDictionary(this IEventDescriptor descriptor)
        {
            var result = new Dictionary <String, String>();

            result["Version"]    = descriptor.Version.ToString();
            result["EntityType"] = descriptor.EntityType;
            result["Timestamp"]  = descriptor.Timestamp.ToString();

            return(result.Merge(descriptor.Headers.ToDictionary(k => k.Key, v => v.Value)));
        }
Ejemplo n.º 4
0
        public virtual IDisposable Observe(IEventDescriptor descriptor, object publisher, object observer,
                                           string methodName)
        {
            var callback = Delegate.CreateDelegate(descriptor.Type, observer, methodName);

            descriptor.Add.Invoke(publisher, callback);

            Action dispose = () => descriptor.Remove.Invoke(publisher, callback);

            return(dispose.ToDisposable());
        }
        public static IDictionary <string, string> ToDictionary(this IEventDescriptor descriptor)
        {
            var result = new Dictionary <string, string>
            {
                ["Version"]    = descriptor.Version.ToString(),
                ["EntityType"] = descriptor.EntityType,
                ["Timestamp"]  = descriptor.Timestamp.ToString(CultureInfo.InvariantCulture)
            };


            return(descriptor.Headers.Merge(result));
        }
        public void Dispatch(Object @event, IEventDescriptor descriptor = null, long?position = null)
        {
            if (_processingQueueSize >= _maxQueueSize)
            {
                throw new SubscriptionCanceled("Processing queue overflow, too many items waiting to be processed");
            }

            QueueTask(new Job
            {
                Event      = @event,
                Descriptor = descriptor,
                Position   = position,
            });
        }
        public virtual IDisposable Observe(IEventDescriptor descriptor, object publisher, object observer,
                                           string methodName)
        {
#if !WINDOWS_UWP && !HAS_CRIPPLEDREFLECTION
            var callback = Delegate.CreateDelegate(descriptor.Type, observer, methodName);

            descriptor.Add.Invoke(publisher, callback);

            Action dispose = () => descriptor.Remove.Invoke(publisher, callback);

            return(dispose.ToDisposable());
#else
            throw new NotImplementedException();
#endif
        }
Ejemplo n.º 8
0
        // Event mutating
        public Object MutateIncoming(Object Event, IEventDescriptor Descriptor, long?Position)
        {
            this.CurrentMessage = Event;
            _workHeaders[Defaults.DomainHeader] = Defaults.Domain.ToString();

            if (Descriptor == null)
            {
                return(Event);
            }

            var headers = Descriptor.Headers;

            // There are certain headers that we can make note of
            // These will be committed to the event stream and included in all .Reply or .Publish done via this Unit Of Work
            // Meaning all receivers of events from the command will get information about the command's message, if they care
            foreach (var header in Defaults.CarryOverHeaders)
            {
                String defaultHeader;
                if (!headers.TryGetValue(header, out defaultHeader))
                {
                    defaultHeader = NotFound;
                }

                var workHeader = String.Format("{0}.{1}", PrefixHeader, header);
                _workHeaders[workHeader] = defaultHeader;
            }

            // Copy any application headers the user might have included
            var userHeaders = headers.Keys.Where(h =>
                                                 !h.Equals("CorrId", StringComparison.InvariantCultureIgnoreCase) &&
                                                 !h.Equals("WinIdName", StringComparison.InvariantCultureIgnoreCase) &&
                                                 !h.StartsWith("NServiceBus", StringComparison.InvariantCultureIgnoreCase) &&
                                                 !h.StartsWith("$", StringComparison.InvariantCultureIgnoreCase));

            foreach (var header in userHeaders)
            {
                _workHeaders[header] = headers[header];
            }

            return(Event);
        }
        internal PerfEvent(ICtfEvent ctfEvent)
        {
            if (!(ctfEvent.EventDescriptor is IEventDescriptor eventDescriptor))
            {
                throw new CtfPlaybackException("Not a valid Perf event.");
            }

            if (ctfEvent.Payload is null)
            {
                throw new CtfPlaybackException("Perf event payload is null.");
            }

            if (!(ctfEvent.Payload is CtfStructValue payload))
            {
                throw new CtfPlaybackException("Perf event payload is not a structure.");
            }

            this.ctfEvent        = ctfEvent;
            this.eventDescriptor = eventDescriptor;

            ///          streamDefinedEventContext
        }
Ejemplo n.º 10
0
        public ReflectionValue(object instance, string getMemberName, string setMemberName, string eventMemberName)
        {
            source = new ReflectionSource <T>(instance, getMemberName, setMemberName);

            memberChanged = (IEventDescriptor)instance.Reflection().FindDescriptor(eventMemberName);

            if (memberChanged == null)
            {
                var propertyChanged = instance as INotifyPropertyChanged;

                if (propertyChanged == null)
                {
                    throw new ArgumentException("Not Supported");
                }

                Disposable.Add(propertyChanged.Observe(OnPropertyChanged));
            }
            else
            {
                Disposable.Add(memberChanged.Observe(instance, this, "OnMemberChanged"));
            }
        }
        // Todo: all the logging and timing can be moved into a "Debug Dispatcher" which can be registered as the IDispatcher if the user wants
        private async Task Process(Object @event, IEventDescriptor descriptor = null, long?position = null)
        {
            var       eventType = _mapper.GetMappedTypeFor(@event.GetType());
            Stopwatch s         = null;

            var handleContext = new HandleContext
            {
                Bus             = _bus,
                EventDescriptor = descriptor
            };

            using (_eventsTimer.NewContext())
            {
                if (Logger.IsDebugEnabled)
                {
                    Logger.DebugFormat("Processing event {0} at position {1}.  Size of queue: {2}/{3}", eventType.FullName, position, _processingQueueSize, _maxQueueSize);
                }


                using (var childBuilder = _builder.CreateChildBuilder())
                {
                    var            handlerGenericType = typeof(IHandleMessagesAsync <>).MakeGenericType(eventType);
                    List <dynamic> handlers           = childBuilder.BuildAll(handlerGenericType).ToList();

                    if (handlers.Count == 0)
                    {
                        return;
                    }

                    var success = false;
                    var retry   = 0;
                    do
                    {
                        var uows = new ConcurrentStack <IEventUnitOfWork>();

                        var mutators = childBuilder.BuildAll <IEventMutator>();

                        if (Logger.IsDebugEnabled)
                        {
                            s = Stopwatch.StartNew();
                        }
                        if (mutators != null && mutators.Any())
                        {
                            Parallel.ForEach(mutators, _parallelOptions, mutate =>
                            {
                                //if (Logger.IsDebugEnabled)
                                Logger.DebugFormat("Mutating incoming event {0} with mutator {1}", eventType.FullName, mutate.GetType().FullName);
                                @event = mutate.MutateIncoming(@event, descriptor, position);
                            });
                        }

                        await childBuilder.BuildAll <IEventUnitOfWork>().ForEachAsync(2, async(uow) =>
                        {
                            uows.Push(uow);
                            uow.Builder = childBuilder;
                            await uow.Begin();
                        });

                        if (Logger.IsDebugEnabled)
                        {
                            s.Stop();
                            Logger.DebugFormat("UOW.Begin for event {0} took {1} ms", eventType.FullName, s.ElapsedMilliseconds);
                        }
                        try
                        {
                            if (Logger.IsDebugEnabled)
                            {
                                s.Restart();
                            }

                            Func <dynamic, Task> processor = async(handler) =>
                            {
                                using (_handlerTimer.NewContext())
                                {
                                    var handlerRetries = 0;
                                    var handlerSuccess = false;
                                    do
                                    {
                                        try
                                        {
                                            Stopwatch handlerWatch = null;
                                            if (Logger.IsDebugEnabled)
                                            {
                                                Logger.DebugFormat("Executing event {0} on handler {1}", eventType.FullName, handler.GetType().FullName);
                                                handlerWatch = Stopwatch.StartNew();
                                            }
                                            var lambda = _objectInvoker.Invoker(handler, eventType);

                                            await lambda(handler, @event, handleContext);

                                            if (Logger.IsDebugEnabled)
                                            {
                                                handlerWatch.Stop();
                                                Logger.DebugFormat("Executing event {0} on handler {1} took {2} ms", eventType.FullName, handler.GetType().FullName, handlerWatch.ElapsedMilliseconds);
                                            }
                                            handlerSuccess = true;
                                        }
                                        catch (RetryException e)
                                        {
                                            Logger.InfoFormat("Received retry signal while dispatching event {0} to {1}. Retry: {2}/3\nException: {3}", eventType.FullName, handler.FullName, handlerRetries, e);
                                            handlerRetries++;
                                        }
                                    } while (!handlerSuccess && (_maxRetries == -1 || handlerRetries <= _maxRetries));

                                    if (!handlerSuccess)
                                    {
                                        Logger.ErrorFormat("Failed executing event {0} on handler {1}", eventType.FullName, handler.FullName);
                                        throw new RetryException(String.Format("Failed executing event {0} on handler {1}", eventType.FullName, handler.FullName));
                                    }
                                }
                            };

                            // Run each handler in parallel (or not) (if handler ever is ASYNC can't use Parallel)
                            if (_parallelHandlers)
                            {
                                await handlers.ForEachAsync(_parallelOptions.MaxDegreeOfParallelism, processor);
                            }
                            else
                            {
                                foreach (var handler in handlers)
                                {
                                    await processor(handler);
                                }
                            }

                            if (Logger.IsDebugEnabled)
                            {
                                s.Stop();
                                Logger.DebugFormat("Processing event {0} took {1} ms", eventType.FullName, s.ElapsedMilliseconds);
                            }
                        }
                        catch (Exception e)
                        {
                            var trailingExceptions = new ConcurrentBag <Exception>();
                            await uows.Generate().ForEachAsync(2, async(uow) =>
                            {
                                try
                                {
                                    await uow.End(e);
                                }
                                catch (Exception endException)
                                {
                                    trailingExceptions.Add(endException);
                                }
                            });

                            if (trailingExceptions.Any())
                            {
                                var exceptions = trailingExceptions.ToList();
                                exceptions.Insert(0, e);
                                e = new System.AggregateException(exceptions);
                            }

                            // Only log if the event has failed more than half max retries indicating a possible non-transient error
                            if (retry > (_maxRetries / 2))
                            {
                                Logger.InfoFormat("Encountered an error while processing {0}. Retry {1}/{2}\nPayload: {3}\nException details:\n{4}", eventType.FullName, retry, _maxRetries, JsonConvert.SerializeObject(@event), e);
                            }
                            else
                            {
                                Logger.DebugFormat("Encountered an error while processing {0}. Retry {1}/{2}\nPayload: {3}\nException details:\n{4}", eventType.FullName, retry, _maxRetries, JsonConvert.SerializeObject(@event), e);
                            }

                            _errorsMeter.Mark();
                            retry++;
                            Thread.Sleep(10);
                            continue;
                        }


                        // Failures when executing UOW.End `could` be transient (network or disk hicup)
                        // A failure of 1 uow in a chain of 5 is a problem as it could create a mangled DB (partial update via one uow then crash)
                        // So we'll just keep retrying the failing UOW forever until it succeeds.
                        if (Logger.IsDebugEnabled)
                        {
                            s.Restart();
                        }
                        var endSuccess = false;
                        var endRetry   = 0;
                        while (!endSuccess)
                        {
                            try
                            {
                                await uows.Generate().ForEachAsync(2, async(uow) =>
                                {
                                    try
                                    {
                                        await uow.End();
                                    }
                                    catch
                                    {
                                        // If it failed it needs to go back on the stack
                                        uows.Push(uow);
                                        throw;
                                    }
                                });

                                endSuccess = true;
                            }
                            catch (Exception e)
                            {
                                if (endRetry > (_maxRetries / 2))
                                {
                                    Logger.ErrorFormat("UOW.End failure while processing event {0} - retry {1}/{3}\nException:\n{2}", eventType.FullName, retry, e, _maxRetries);
                                }
                                else
                                {
                                    Logger.DebugFormat("UOW.End failure while processing event {0} - retry {1}/{3}\nException:\n{2}", eventType.FullName, retry, e, _maxRetries);
                                }
                                endRetry++;
                                Thread.Sleep(50);
                            }
                        }
                        if (Logger.IsDebugEnabled)
                        {
                            s.Stop();
                            Logger.DebugFormat("UOW.End for event {0} took {1} ms", eventType.FullName, s.ElapsedMilliseconds);
                        }
                        success = true;
                    } while (!success && (_maxRetries == -1 || retry < _maxRetries));

                    if (!success)
                    {
                        var message = String.Format("Encountered an error while processing {0}.  Ran out of retries, dropping event.\nPayload: {3}", eventType.FullName, JsonConvert.SerializeObject(@event));
                        if (_dropEventFatal)
                        {
                            Logger.Fatal(message);
                            throw new SubscriptionCanceled(message);
                        }

                        Logger.Error(message);
                    }
                }
            }
            _eventsMeter.Mark();
        }
Ejemplo n.º 12
0
        private IEnumerable <MethodInfo> GenerateExecutableMethods(IEventListener listener, IEventDescriptor eventInfo)
        {
            string eventType = EventTypeAttribute.GetEventType(listener);

            if (eventType != eventInfo.EventType)
            {
                return(Enumerable.Empty <MethodInfo>());
            }

            return(listener.GetType()
                   .GetMethods()
                   .Where(method =>
            {
                var ps = method.GetParameters();
                return ps.Length == 0 || ps.Length == 1;
            })
                   .Where(method =>
            {
                string eventName = EventNameAttribute.GetEventName(method);
                return eventName == eventInfo.EventName;
            }).ToList());
        }
Ejemplo n.º 13
0
        private IEnumerable <MethodInfo> GetExecutableMethods(IEventListener listener, IEventDescriptor eventInfo)
        {
            string cacheKey = $"{listener.GetType().FullName} @ {eventInfo.EventType}.{eventInfo.EventName}";

            return(this.cache.GetOrCreate <IEnumerable <MethodInfo> >(cacheKey, () => GenerateExecutableMethods(listener, eventInfo)));
        }
Ejemplo n.º 14
0
 public static IDisposable Observe(this IEventDescriptor descriptor, object publisher, object observer,
                                   string methodName)
 {
     return(Extensions.Observe(descriptor, publisher, observer, methodName));
 }
Ejemplo n.º 15
0
 public EventDescriptorNode(IEventDescriptor eventDescriptor) => _eventDescriptor = eventDescriptor;