Beispiel #1
0
 public static IEventObservable <TEvent, IEventContext, TModel> GetEventObservable <TEvent, TModel>(this IRouter <TModel> router, IEventHoldingStrategy <TEvent, TModel> strategy)
     where TEvent : IIdentifiableEvent
     where TModel : IHeldEventStore
 {
     return(EventObservable.Create <TEvent, IEventContext, TModel>(
                o =>
     {
         var heldEvents = new Dictionary <Guid, HeldEventData <TEvent> >();
         var releasedEvents = new HashSet <Guid>();
         var disposables = new CollectionDisposable();
         disposables.Add(router.GetEventObservable <TEvent>(ObservationStage.Preview).Observe((e, c, m) =>
         {
             // Have we already re-published this event? If so we don't want to hold it again.
             if (releasedEvents.Contains(e.Id))
             {
                 releasedEvents.Remove(e.Id);
                 o.OnNext(e, c, m);
             }
             else
             {
                 var shouldHoldEvent = strategy.ShouldHold(e, c, m);
                 if (shouldHoldEvent)
                 {
                     // Cancel the event so no other observers will receive it.
                     c.Cancel();
                     // Model that we've cancelled it, other code can now reflect the newly modelled values.
                     // That is other code needs to determine what to do with these held events on the model.
                     // When it figures that out it should raise a HeldEventActionEvent so we can proceed here.
                     IEventDescription eventDescription = strategy.GetEventDescription(e, m);
                     m.AddHeldEventDescription(eventDescription);
                     // finally we hold the event locally
                     heldEvents.Add(e.Id, new HeldEventData <TEvent>(eventDescription, e));
                 }
             }
         }));
         disposables.Add(router.GetEventObservable <HeldEventActionEvent>().Observe((e, c, m) =>
         {
             HeldEventData <TEvent> heldEventData;
             // Since we're listening to a pipe of all events we need to filter out anything we don't know about.
             if (heldEvents.TryGetValue(e.EventId, out heldEventData))
             {
                 // We're received an event to clean up.
                 heldEvents.Remove(e.EventId);
                 m.RemoveHeldEventDescription(heldEventData.EventDescription);
                 if (e.Action == HeldEventAction.Release)
                 {
                     // Temporarily store the event we're republishing so we don't re-hold it
                     releasedEvents.Add(e.EventId);
                     router.PublishEvent(heldEventData.Event);
                 }
             }
         }));
         return disposables;
     }
                ));
 }
                public void Issue45TestCase_OpenGenerics()
                {
                    var router = new Router <TestModel>(new TestModel());
                    var stream = EventObservable.Merge <BaseEvent, IEventContext, TestModel>(
                        router.GetEventObservable <Foo <string> >(),
                        router.GetEventObservable <Foo <int> >()
                        );

                    stream.Observe((ev, model) => Assert.Pass());
                    router.PublishEvent(new Foo <string>());
                    Assert.Fail();
                }
Beispiel #3
0
 public static IEventObservable <TBaseEvent, IEventContext, TModel> GetEventObservable <TEvent, TBaseEvent, TModel>(this IRouter <TModel> router, IEventHoldingStrategy <TEvent, TBaseEvent, TModel> strategy)
     where TEvent : TBaseEvent, IIdentifiableEvent
     where TModel : IHeldEventStore
 {
     object[] parameters = new object[] { router, strategy };
     return(EventObservable.Create <TBaseEvent, IEventContext, TModel>(
                o =>
     {
         var getEventStreamMethod = GetEventObservableMethodInfo.MakeGenericMethod(typeof(TEvent), typeof(TModel));
         dynamic observable = getEventStreamMethod.Invoke(null, parameters);
         return (IDisposable)observable.Observe(o);
     }
                ));
 }
                public void CanMergeEventStreams()
                {
                    var receivedEvents = new List <BaseEvent>();
                    var stream         = EventObservable.Merge(
                        _router.GetEventObservable <BaseEvent, TestModel>(_model1.Id),                        // stream 1
                        _router.GetEventObservable <Event2, TestModel>(_model1.Id, ObservationStage.Preview), // stream 2
                        _router.GetEventObservable <Event3, TestModel>(_model1.Id)                            // stream 3
                        );

                    stream.Observe((baseEvent, context, model) =>
                    {
                        receivedEvents.Add(baseEvent);
                    });
                    _router.PublishEvent(_model1.Id, new Event1());
                    receivedEvents.Count.ShouldBe(1); // stream 1 should procure
                    _router.PublishEvent(_model1.Id, new Event2());
                    receivedEvents.Count.ShouldBe(3); // stream 1 and 2 should procure
                    _router.PublishEvent(_model1.Id, new Event3());
                    receivedEvents.Count.ShouldBe(5); // stream 1 and 3 should procure
                }
Beispiel #5
0
            /// <summary>
            /// Returns an IEventObservable that will yield events of type TEvent when observed.
            /// </summary>
            /// <typeparam name="TEvent">Type type of event to observe</typeparam>
            /// <param name="observationStage">The stage in the event processing workflow you wish to observe at</param>
            /// <returns></returns>
            public IEventObservable <TEvent, IEventContext, TModel> GetEventObservable <TEvent>(ObservationStage observationStage = ObservationStage.Normal)
            {
                return(EventObservable.Create <TEvent, IEventContext, TModel>(o =>
                {
                    _state.ThrowIfHalted();
                    EventSubjects <TEvent> eventSubjects;
                    lock (_gate)
                    {
                        var eventType = typeof(TEvent);
                        if (!_eventSubjects.ContainsKey(eventType))
                        {
                            eventSubjects = new EventSubjects <TEvent>(_eventObservationRegistrar);
                            _eventSubjects[eventType] = eventSubjects;
                        }
                        else
                        {
                            eventSubjects = (EventSubjects <TEvent>)_eventSubjects[eventType];
                        }
                    }
                    EventSubject <TEvent, IEventContext, TModel> subject;
                    switch (observationStage)
                    {
                    case ObservationStage.Preview:
                        subject = eventSubjects.PreviewSubject;
                        break;

                    case ObservationStage.Normal:
                        subject = eventSubjects.NormalSubject;
                        break;

                    case ObservationStage.Committed:
                        subject = eventSubjects.CommittedSubject;
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(string.Format("observationStage {0} not supported", observationStage));
                    }
                    return subject.Observe(o);
                }));
            }