예제 #1
0
        public Task ReceiveAsync(IContext context)
        {
            switch (context.Message)
            {
            case Publish publish:
                foreach ((PID, object)tuple in _subscriptions.Select(publish.Topic, publish.Message))
                {
                    tuple.Item1.Tell(publish);
                }

                return(Task.CompletedTask);

            case Subscribe subscribe:
                SubscriptionInfo subscriptionInfo = new SubscriptionInfo(Type.GetType(subscribe.Type), subscribe.Topic);
                _subscriptions.Add(subscriptionInfo, subscribe.ConsumerActor);
                SubscribeAck subscribeAck = new SubscribeAck
                {
                    SubscriptionId = ByteString.CopyFrom(subscriptionInfo.SubscriptionId.ToByteArray())
                };
                context.Respond(subscribeAck);
                return(Task.CompletedTask);

            case Unsubscribe unsubscribe:
                UnsubscribeAck unsubscribeAck = new UnsubscribeAck
                {
                    Success = _subscriptions.Remove(new Guid(unsubscribe.SubscriptionId.ToByteArray()))
                };
                context.Respond(unsubscribeAck);
                return(Task.CompletedTask);

            default:
                return(Task.CompletedTask);
            }
        }
 public void Handle(SubscribeAck msg)
 {
     _subscriptionWaiter?.Tell(msg);
     Log.Trace(
         "Subscription was successfull for topic {Topic} group {Group} path {Path}",
         msg.Subscribe.Topic, msg.Subscribe.Group, msg.Subscribe.Ref.Path);
 }
        public async Task when_subscribing_new_topics_then_subscriptions_are_created_and_ack_is_sent()
        {
            MqttConfiguration configuration = new MqttConfiguration {
                MaximumQualityOfService = MqttQualityOfService.AtLeastOnce
            };
            Mock <IMqttTopicEvaluator>          topicEvaluator      = new Mock <IMqttTopicEvaluator>();
            Mock <IRepository <ClientSession> > sessionRepository   = new Mock <IRepository <ClientSession> >();
            IPacketIdProvider             packetIdProvider          = Mock.Of <IPacketIdProvider>();
            IRepository <RetainedMessage> retainedMessageRepository = Mock.Of <IRepository <RetainedMessage> >();
            IPublishSenderFlow            senderFlow = Mock.Of <IPublishSenderFlow>();

            string        clientId = Guid.NewGuid().ToString();
            ClientSession session  = new ClientSession(clientId, clean: false);

            topicEvaluator.Setup(e => e.IsValidTopicFilter(It.IsAny <string>())).Returns(true);
            sessionRepository.Setup(r => r.Read(It.IsAny <string>())).Returns(session);

            MqttQualityOfService fooQoS          = MqttQualityOfService.AtLeastOnce;
            string               fooTopic        = "test/foo/1";
            Subscription         fooSubscription = new Subscription(fooTopic, fooQoS);
            MqttQualityOfService barQoS          = MqttQualityOfService.AtMostOnce;
            string               barTopic        = "test/bar/1";
            Subscription         barSubscription = new Subscription(barTopic, barQoS);

            ushort    packetId  = (ushort)new Random().Next(0, ushort.MaxValue);
            Subscribe subscribe = new Subscribe(packetId, fooSubscription, barSubscription);

            Mock <IMqttChannel <IPacket> > channel = new Mock <IMqttChannel <IPacket> >();

            IPacket response = default;

            channel.Setup(c => c.SendAsync(It.IsAny <IPacket>()))
            .Callback <IPacket>(p => response = p)
            .Returns(Task.Delay(0));

            Mock <IConnectionProvider> connectionProvider = new Mock <IConnectionProvider>();

            connectionProvider
            .Setup(p => p.GetConnection(It.Is <string>(c => c == clientId)))
            .Returns(channel.Object);

            ServerSubscribeFlow flow = new ServerSubscribeFlow(topicEvaluator.Object, sessionRepository.Object,
                                                               retainedMessageRepository, packetIdProvider, senderFlow, configuration);

            await flow.ExecuteAsync(clientId, subscribe, channel.Object);

            sessionRepository.Verify(r => r.Update(It.Is <ClientSession>(s => s.Id == clientId && s.Subscriptions.Count == 2 &&
                                                                         s.Subscriptions.All(x => x.TopicFilter == fooTopic || x.TopicFilter == barTopic))));
            Assert.NotNull(response);

            SubscribeAck subscribeAck = response as SubscribeAck;

            Assert.NotNull(subscribeAck);
            packetId.Should().Be(subscribeAck.PacketId);
            2.Should().Be(subscribeAck.ReturnCodes.Count());
            Assert.True(subscribeAck.ReturnCodes.Any(c => c == SubscribeReturnCode.MaximumQoS0));
            Assert.True(subscribeAck.ReturnCodes.Any(c => c == SubscribeReturnCode.MaximumQoS1));
        }
예제 #4
0
 private void Handle(SubscribeAck msg)
 {
     if (msg.Subscribe.Topic.Equals("NamedTopic") &&
         msg.Subscribe.Ref.Equals(Self) &&
         msg.Subscribe.Group == null)
     {
         _log.Info($">>> Recevied message : {msg}, Sender: {Sender}");
     }
 }
예제 #5
0
 private void Handle(SubscribeAck msg)
 {
     if (msg.Subscribe.Topic.Equals(topicname) &&
         msg.Subscribe.Ref.Equals(Self) &&
         msg.Subscribe.Group.Equals(groupname))
     {
         _log.Info($" Group:{groupname} Recevied message : {msg}, Sender: {Sender}");
     }
 }
예제 #6
0
        public void when_writing_invalid_subscribe_ack_packet_then_fails(string jsonPath)
        {
            jsonPath = Path.Combine(Environment.CurrentDirectory, jsonPath);

            SubscribeAckFormatter formatter    = new SubscribeAckFormatter();
            SubscribeAck          subscribeAck = Packet.ReadPacket <SubscribeAck>(jsonPath);

            AggregateException ex = Assert.Throws <AggregateException>(() => formatter.FormatAsync(subscribeAck).Wait());

            Assert.True(ex.InnerException is MqttProtocolViolationException);
        }
예제 #7
0
        public async Task when_writing_subscribe_ack_packet_then_succeeds(string jsonPath, string packetPath)
        {
            jsonPath   = Path.Combine(Environment.CurrentDirectory, jsonPath);
            packetPath = Path.Combine(Environment.CurrentDirectory, packetPath);

            byte[] expectedPacket              = Packet.ReadAllBytes(packetPath);
            SubscribeAckFormatter formatter    = new SubscribeAckFormatter();
            SubscribeAck          subscribeAck = Packet.ReadPacket <SubscribeAck>(jsonPath);

            byte[] result = await formatter.FormatAsync(subscribeAck);

            expectedPacket.Should().BeEquivalentTo(result);
        }
예제 #8
0
        public async Task when_reading_subscribe_ack_packet_then_succeeds(string packetPath, string jsonPath)
        {
            packetPath = Path.Combine(Environment.CurrentDirectory, packetPath);
            jsonPath   = Path.Combine(Environment.CurrentDirectory, jsonPath);

            SubscribeAck          expectedSubscribeAck = Packet.ReadPacket <SubscribeAck>(jsonPath);
            SubscribeAckFormatter formatter            = new SubscribeAckFormatter();

            byte[] packet = Packet.ReadAllBytes(packetPath);

            IPacket result = await formatter.FormatAsync(packet);

            expectedSubscribeAck.Should().Be(result);
        }
예제 #9
0
 public Subscribed(SubscribeAck ack, IActorRef subscriber)
 {
     Ack        = ack;
     Subscriber = subscriber;
 }
예제 #10
0
 public Subscribed(SubscribeAck ack, IActorRef subscriber)
 {
     Ack = ack;
     Subscriber = subscriber;
 }
예제 #11
0
 private void Process(SubscribeAck eventToProcess)
 {
     LoggingAdapter.Debug("Received subscribe ack " + subscriptionMessage.SubscriptionId.Id);
 }
예제 #12
0
 private void Process(SubscribeAck eventToProcess)
 {
     LoggingAdapter.Debug("Received subscribe ack " + subscriptionMessage.SubscriptionId.Id);
 }
예제 #13
0
        public ProtoBrokerSubject(PID brokerPid,
                                  string topic,
                                  string consumerGroup)
        {
            if (brokerPid == null)
            {
                throw new ArgumentNullException(nameof(brokerPid));
            }

            _topic = topic ?? throw new ArgumentNullException(nameof(topic));

            GetPublisherPiDsResponse getPublisherPiDsResponse = brokerPid.RequestAsync <GetPublisherPiDsResponse>(new GetPublisherPiDs()).Result;

            PID[] publishers = getPublisherPiDsResponse.PIds.ToArray();
            int   hash       = Math.Abs(topic.GetHashCode());

            _publisherPid = publishers[hash % publishers.Length];

            _observable = Observable.Create <T>(async(observer, cancellationToken) =>
            {
                try
                {
                    Props props               = Actor.FromProducer(() => new ConsumerActor <T>(observer));
                    PID consumerActor         = Actor.SpawnPrefix(props, $"Consumer_{topic}_{consumerGroup}");
                    Subscribe addSubscription = new Subscribe
                    {
                        ConsumerActor = consumerActor,
                        Topic         = topic,
                        Type          = typeof(T).FullName
                    };

                    List <SubscribeAck> subscriptions = new List <SubscribeAck>();
                    foreach (PID publisher in publishers.EmptyIfNull())
                    {
                        SubscribeAck subscribeAck = await publisher
                                                    .RequestAsync <SubscribeAck>(addSubscription)
                                                    .ConfigureAwait(false);
                        subscriptions.Add(subscribeAck);
                    }

                    try
                    {
                        await Task.Delay(-1, cancellationToken).ConfigureAwait(false);
                    }
                    finally
                    {
                        foreach (SubscribeAck subscription in subscriptions)
                        {
                            Unsubscribe removeSubscription = new Unsubscribe
                            {
                                SubscriptionId = subscription.SubscriptionId
                            };
                            await Task.WhenAll(publishers
                                               .Select(publisher => publisher.RequestAsync <UnsubscribeAck>(removeSubscription)))
                            .ConfigureAwait(false);
                        }

                        consumerActor.Stop();
                    }

                    observer.OnCompleted();
                }
                catch (OperationCanceledException)
                {
                    observer.OnCompleted();
                }
                catch (Exception e)
                {
                    observer.OnError(e);
                }
            })
                          .Retry()
                          .Publish()
                          .RefCount();
        }