Exemple #1
0
        public async Task <string> Watch <T>(string actorInterface, string eventName, string actorId, Action <ActorEvent <T> > handler)
        {
            var channel = ActorEventChannel(actorInterface, eventName, actorId);

            SubscriptionHandler action = (string c, ref byte[] data) => {
                var e = new ActorEvent <T>()
                {
                    ActorInterface = actorInterface,
                    EventName      = eventName,
                    EventData      = _serializer.Deserialize <T>(data),
                    ActorId        = c.Split(':').Last()
                };

                handler(e);
            };

            var guid = Guid.NewGuid().ToString();

            _subscriptions[guid] = new PubSubSubscription()
            {
                Channel = channel, Handler = action
            };

            await _pubsub.Subscribe(channel, action);

            return(guid);
        }
Exemple #2
0
        public static async Task <TResponse> RequestAsync <TRequest, TResponse>(this IPubSub pubsub, TRequest message, TimeSpan timeout, bool self = true)
        {
            var request = new Request <TRequest> {
                Body = message, CorrelationId = Guid.NewGuid()
            };

            IDisposable subscription = null;

            try
            {
                var receiveTask = new TaskCompletionSource <TResponse>(TaskCreationOptions.RunContinuationsAsynchronously);

                subscription = pubsub.Subscribe <Response <TResponse> >(response =>
                {
                    if (response.CorrelationId == request.CorrelationId)
                    {
                        receiveTask.SetResult(response.Body);
                    }
                });

                Task.Run(() => pubsub.Publish(request, self));

                using (var cts = new CancellationTokenSource(timeout))
                {
                    return(await receiveTask.Task.WithCancellation(cts.Token));
                }
            }
            finally
            {
                subscription?.Dispose();
            }
        }
Exemple #3
0
        public async Task Should_write_to_store_with_previous_version()
        {
            InvalidateMessage message = null;

            pubSub.Subscribe <InvalidateMessage>(m =>
            {
                message = m;
            });

            A.CallTo(() => snapshotStore.ReadAsync(key))
            .Returns((123, 13));

            var actualObject = await sut.GetSingleAsync <MyStatefulObject, string>(key);

            Assert.Same(statefulObject, actualObject);
            Assert.Equal(123, statefulObject.State);

            statefulObject.SetState(456);

            await statefulObject.WriteStateAsync();

            A.CallTo(() => snapshotStore.WriteAsync(key, 456, 13, 14))
            .MustHaveHappened();

            Assert.NotNull(message);
            Assert.Equal(key, message.Key);
        }
Exemple #4
0
        public async Task Should_write_to_store_with_previous_etag()
        {
            var etag = Guid.NewGuid().ToString();

            InvalidateMessage message = null;

            pubSub.Subscribe <InvalidateMessage>(m =>
            {
                message = m;
            });

            A.CallTo(() => store.ReadAsync <int>(key))
            .Returns((123, etag));

            var actual = await sut.GetAsync <MyStatefulObject, int>(key);

            Assert.Same(state, actual);
            Assert.Equal(123, state.State);

            state.SetState(456);

            await state.WriteStateAsync();

            A.CallTo(() => store.WriteAsync(key, 456, etag, A <string> .That.Matches(x => x != null)))
            .MustHaveHappened();

            Assert.NotNull(message);
            Assert.Equal(key, message.Key);
        }
        public async Task Should_write_to_store_with_previous_position()
        {
            InvalidateMessage message = null;

            pubSub.Subscribe <InvalidateMessage>(m =>
            {
                message = m;
            });

            SetupEventStore(3);

            var actualObject = await sut.GetSingleAsync <MyStatefulObject>(key);

            Assert.Same(statefulObject, actualObject);

            await statefulObject.WriteEventsAsync(new MyEvent(), new MyEvent());

            await statefulObject.WriteEventsAsync(new MyEvent(), new MyEvent());

            A.CallTo(() => eventStore.AppendEventsAsync(A <Guid> .Ignored, key, 2, A <ICollection <EventData> > .That.Matches(x => x.Count == 2)))
            .MustHaveHappened();
            A.CallTo(() => eventStore.AppendEventsAsync(A <Guid> .Ignored, key, 4, A <ICollection <EventData> > .That.Matches(x => x.Count == 2)))
            .MustHaveHappened();

            Assert.NotNull(message);
            Assert.Equal(key, message.Key);
        }
 public override void InitializePresenter(dynamic context)
 {
     _view           = (IQueryWindowControl)context.QueryWindowControl;
     _view.Presenter = this;
     _pubsub         = context.PubSub;
     _pubsub.Subscribe(this, Constants.SubscriptionTypes.THEME_CHANGE);
     TabIndexReference = (int)context.TabIndexReference;
 }
Exemple #7
0
        public void InitializePresenter(dynamic context)
        {
            _context        = context;
            _view           = (IActionLogForm)context.ActionLogForm;
            _view.Presenter = this;

            _pubsub = context.PubSub;
            _pubsub.Subscribe(this, Constants.SubscriptionTypes.THEME_CHANGE);
        }
Exemple #8
0
        public void InitializePresenter(dynamic context)
        {
            _context        = context;
            _view           = (IMainForm)context.MainForm;
            _view.Presenter = this;
            _pubsub         = context.PubSub;
            _pubsub.Subscribe(this, Constants.SubscriptionTypes.THEME_CHANGE);

            InitializeTransactionCache();
        }
Exemple #9
0
 public void Initialize()
 {
     pubSubSubscription = pubSub.Subscribe <InvalidateMessage>(m =>
     {
         lock (lockObject)
         {
             statesCache.Remove(m.Key);
         }
     });
 }
Exemple #10
0
        public InvalidatingMemoryCache(IMemoryCache inner, IPubSub invalidator)
        {
            Guard.NotNull(inner, nameof(inner));
            Guard.NotNull(invalidator, nameof(invalidator));

            this.inner       = inner;
            this.invalidator = invalidator;

            invalidator.Subscribe(ChannelName, inner.Remove);
        }
Exemple #11
0
        public static IDisposable ReceiveAsync <TRequest, TResponse>(this IPubSub pubsub, Func <TRequest, Task <TResponse> > callback, bool self = true)
        {
            return(pubsub.Subscribe <Request <TRequest> >(async x =>
            {
                var response = await callback(x.Body);

                pubsub.Publish(new Response <TResponse> {
                    CorrelationId = x.CorrelationId, Body = response
                }, true);
            }));
        }
        public InvalidatingMemoryCache(IMemoryCache inner, IPubSub invalidator)
        {
            Guard.NotNull(inner, nameof(inner));
            Guard.NotNull(invalidator, nameof(invalidator));

            this.inner       = inner;
            this.invalidator = invalidator;

            subscription = invalidator.Subscribe <InvalidateMessage>(m =>
            {
                inner.Remove(m.CacheKey);
            });
        }
Exemple #13
0
        public void Should_send_invalidation_message_on_refresh()
        {
            InvalidateMessage message = null;

            pubSub.Subscribe <InvalidateMessage>(m =>
            {
                message = m;
            });

            sut.Synchronize <MyStatefulObject, string>(key);

            Assert.NotNull(message);
            Assert.Equal(key, message.Key);
        }
Exemple #14
0
        /// <summary>
        /// Subscribes to a stream of messages that match a .NET type.
        /// </summary>
        /// <typeparam name="T">The type to subscribe to</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="subscriptionId">
        /// A unique identifier for the subscription. Two subscriptions with the same subscriptionId
        /// and type will get messages delivered in turn. This is useful if you want multiple subscribers
        /// to load balance a subscription in a round-robin fashion.
        /// </param>
        /// <param name="onMessage">
        /// The action to run when a message arrives. When onMessage completes the message
        /// receipt is Ack'd. All onMessage delegates are processed on a single thread so you should
        /// avoid long running blocking IO operations. Consider using SubscribeAsync
        /// </param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// An <see cref="ISubscriptionResult"/>
        /// Call Dispose on it or on its <see cref="ISubscriptionResult.ConsumerCancellation"/> to cancel the subscription.
        /// </returns>
        public static ISubscriptionResult Subscribe <T>(
            this IPubSub pubSub,
            string subscriptionId,
            Action <T> onMessage,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            return(pubSub.Subscribe(
                       subscriptionId,
                       onMessage,
                       c => { },
                       cancellationToken
                       ));
        }
Exemple #15
0
        /// <summary>
        /// Subscribes to a stream of messages that match a .NET type.
        /// Allows the subscriber to complete asynchronously.
        /// </summary>
        /// <typeparam name="T">The type to subscribe to</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="subscriptionId">
        /// A unique identifier for the subscription. Two subscriptions with the same subscriptionId
        /// and type will get messages delivered in turn. This is useful if you want multiple subscribers
        /// to load balance a subscription in a round-robin fashion.
        /// </param>
        /// <param name="onMessage">
        /// The action to run when a message arrives. onMessage can immediately return a Task and
        /// then continue processing asynchronously. When the Task completes the message will be
        /// Ack'd.
        /// </param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// An <see cref="ISubscriptionResult"/>
        /// Call Dispose on it or on its <see cref="ISubscriptionResult.ConsumerCancellation"/> to cancel the subscription.
        /// </returns>
        public static ISubscriptionResult Subscribe <T>(
            this IPubSub pubSub,
            string subscriptionId,
            Func <T, Task> onMessage,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            return(pubSub.Subscribe <T>(
                       subscriptionId,
                       (m, c) => onMessage(m),
                       c => { },
                       cancellationToken
                       ));
        }
        public void Subscribe(string recipient, Action <object> handler)
        {
            Guard.NotNullOrEmpty(recipient, nameof(recipient));

            pubSub.Subscribe(ChannelName, json =>
            {
                var envelope = JsonConvert.DeserializeObject <Envelope>(json);

                if (string.Equals(envelope.Recipient, recipient, StringComparison.OrdinalIgnoreCase))
                {
                    var messageType = typeNameRegistry.GetType(envelope.PayloadType);
                    var messageBody = ReadJson(envelope.Payload, messageType);

                    handler?.Invoke(messageBody);
                }
            });
        }
Exemple #17
0
        public async Task SubscribeAsync(Func <PunchyMessage, Task> onMessageAsync, string groupId, CancellationToken cancellationToken, params string[] topics)
        {
            if (onMessageAsync == null)
            {
                throw new ArgumentNullException(nameof(onMessageAsync));
            }

            if (groupId == null)
            {
                throw new ArgumentNullException(nameof(groupId));
            }

            if (!TopicNameHelpers.IsValid(groupId))
            {
                throw new ArgumentException(
                          $"The groupId must match regex pattern: '{TopicNameHelpers.TopicOrGroupIdValidationRegexPattern}'", nameof(groupId));
            }

            var messageHandler = new MessageHandler(onMessageAsync, pubSub, logger, configuration, groupId);
            var retryerTopics  = new List <string>();

            foreach (var topic in topics)
            {
                if (!TopicNameHelpers.IsValid(topic))
                {
                    throw new ArgumentException(
                              $"The topic name must match regex pattern: '{TopicNameHelpers.TopicOrGroupIdValidationRegexPattern}'. " +
                              $"Validation failed for '{topic}'.", nameof(topics));
                }

                if (!TopicNameHelpers.IsBadMessageTopic(topic))
                {
                    for (int i = 0; i < configuration.LevelDelaysInSeconds.Length; i++)
                    {
                        retryerTopics.Add(TopicNameHelpers.BuildBadMessageTopicName(topic, i, groupId));
                    }
                }
            }

            var subscription = pubSub.Subscribe(messageHandler, groupId, topics.Union(retryerTopics).ToArray());

            messageHandler.Subscription = subscription;
            await subscription.StartAsync(cancellationToken);
        }
Exemple #18
0
        /// <summary>
        /// Subscribes to a stream of messages that match a .NET type.
        /// </summary>
        /// <typeparam name="T">The type to subscribe to</typeparam>
        /// <param name="pubSub">The pubSub instance</param>
        /// <param name="subscriptionId">
        /// A unique identifier for the subscription. Two subscriptions with the same subscriptionId
        /// and type will get messages delivered in turn. This is useful if you want multiple subscribers
        /// to load balance a subscription in a round-robin fashion.
        /// </param>
        /// <param name="onMessage">
        /// The action to run when a message arrives. When onMessage completes the message
        /// receipt is Ack'd. All onMessage delegates are processed on a single thread so you should
        /// avoid long running blocking IO operations. Consider using SubscribeAsync
        /// </param>
        /// <param name="configure">
        /// Fluent configuration e.g. x => x.WithTopic("uk.london")
        /// </param>
        /// <param name="cancellationToken">The cancellation token</param>
        /// <returns>
        /// An <see cref="ISubscriptionResult"/>
        /// Call Dispose on it or on its <see cref="ISubscriptionResult.ConsumerCancellation"/> to cancel the subscription.
        /// </returns>
        public static ISubscriptionResult Subscribe <T>(
            this IPubSub pubSub,
            string subscriptionId,
            Action <T> onMessage,
            Action <ISubscriptionConfiguration> configure,
            CancellationToken cancellationToken = default
            )
        {
            Preconditions.CheckNotNull(pubSub, "pubSub");

            var onMessageAsync = TaskHelpers.FromAction <T>((m, c) => onMessage(m));

            return(pubSub.Subscribe(
                       subscriptionId,
                       onMessageAsync,
                       configure,
                       cancellationToken
                       ));
        }
Exemple #19
0
        public static async Task <TResponse> RequestAsync <TRequest, TResponse>(this IPubSub pubsub, TRequest message, TimeSpan timeout, bool self = true)
        {
            var request = new Request <TRequest> {
                Body = message, CorrelationId = Guid.NewGuid()
            };

            IDisposable subscription = null;

            try
            {
                var receiveTask = new TaskCompletionSource <TResponse>();

                subscription = pubsub.Subscribe <Response <TResponse> >(response =>
                {
                    if (response.CorrelationId == request.CorrelationId)
                    {
                        receiveTask.SetResult(response.Body);
                    }
                });

                Task.Run(() => pubsub.Publish(request, self));

                var firstTask = await Task.WhenAny(receiveTask.Task, Task.Delay(timeout));

                if (firstTask.Id != receiveTask.Task.Id)
                {
                    throw new TaskCanceledException();
                }
                else
                {
                    return(await receiveTask.Task);
                }
            }
            finally
            {
                subscription?.Dispose();
            }
        }
Exemple #20
0
 public IDisposable Subscribe(Action handler)
 {
     return(invalidator.Subscribe(ChannelName, x => handler()));
 }
 public IDisposable Subscribe(Action <string> handler)
 {
     return(pubsub.Subscribe <EventNotification>(x => handler?.Invoke(x.StreamName)));
 }
Exemple #22
0
 public void Init(IPubSub pubSub)
 {
     pubSub.Subscribe <FileReadProgressEvent>(ProgressUpdaterDelegate);
 }
 /// <summary>
 /// 订阅
 /// </summary>
 /// <param name="channel"></param>
 /// <param name="action"></param>
 public void Subscribe(string channel, Action <string> action)
 {
     pubsub.Subscribe(channel, action);
 }
Exemple #24
0
        public void PublishSimpleTest()
        {
            var recorder = new Recorder <int>();

            _pubSub.Subscribe("/temperature", recorder.Handler);
            _pubSub.Publish("/temperature", 25);

            var expected = Tuple.Create("/temperature", 25);

            recorder.Messages.Should()
            .ContainSingle(tuple => Equals(tuple, expected));
        }
Exemple #25
0
 public IDisposable Subscribe(Action <string> handler)
 {
     return(pubsub.Subscribe(ChannelName, x => handler?.Invoke(x)));
 }
Exemple #26
0
 public void Subscribe(Action handler)
 {
     invalidator.Subscribe(ChannelName, x => handler());
 }