Exemple #1
0
        public async Task ReceiveAsync(IContext context)
        {
            switch (context.Message)
            {
            case Started _:
                Console.Out.WriteLine("Started: " + context.Self.Id);

                Actor.EventStream.Subscribe <ClusterTopologyEvent>(clusterTopologyEvent =>
                {
                    Console.Out.WriteLine("Got inner ClusterTopologyEvent");
                    context.Self.Tell(clusterTopologyEvent);
                });
                break;

            case PID brokerPid:
                _brokers.Add(brokerPid);
                context.Watch(brokerPid);
                break;

            case Terminated terminated:
                _brokers.Remove(terminated.Who);
                context.Unwatch(terminated.Who);
                break;

            case ClusterTopologyEvent clusterTopologyEvent:
                Console.Out.WriteLine("clusterTopologyEvent");
                _brokers.Clear();
                foreach (MemberStatus memberStatus in clusterTopologyEvent.Statuses)
                {
                    if (memberStatus.Alive)
                    {
                        PID remoteBrokerActorPid = new PID(memberStatus.Address, context.Self.Id);
                        GetPublisherPiDsResponse getPublisherPiDsResponse = await remoteBrokerActorPid
                                                                            .RequestAsync <GetPublisherPiDsResponse>(new GetPublisherPiDs())
                                                                            .ConfigureAwait(false);
                    }
                }

                break;
            }
        }
Exemple #2
0
        public Task ReceiveAsync(IContext context)
        {
            switch (context.Message)
            {
            case Started _:
                _brokerMasterActor.Tell(context.Self);

                Props props = Actor.FromProducer(() => new PublisherActor());
                foreach (int _ in Enumerable.Range(0, Environment.ProcessorCount))
                {
                    PID publisher = context.SpawnPrefix(props, nameof(PublisherActor));
                    context.Watch(publisher);
                    _publisherActors.Add(publisher);
                }

                _clusterTopologyChangedSubscription = Actor.EventStream.Subscribe <ClusterTopologyEvent>(clusterTopologyEvent =>
                {
                    _brokerMasterActor.Tell(context.Self);
                });

                break;

            case Stopped _:
                _clusterTopologyChangedSubscription?.Unsubscribe();

                foreach (Subscription subscription in _subscriptions)
                {
                    TellAll(new Unsubscribe {
                        SubscriptionId = subscription.SubscriptionId
                    });
                }

                break;

            case GetPublisherPiDs _:
                GetPublisherPiDsResponse response = new GetPublisherPiDsResponse();
                response.PIds.AddRange(_publisherActors);
                context.Respond(response);
                break;

            case Subscribe subscribe:
                Subscription newSubscription = new Subscription
                {
                    SubscriptionId = ByteString.CopyFrom(Guid.NewGuid().ToByteArray()),
                    Subscriber     = subscribe
                };
                _subscriptions.Add(newSubscription);
                TellAll(newSubscription);
                break;

            case Unsubscribe unsubscribe:
                _subscriptions.RemoveWhere(subscription => unsubscribe.SubscriptionId == subscription.SubscriptionId);
                TellAll(unsubscribe);
                break;

            case Terminated terminated:
                _publisherActors.Remove(terminated.Who);
                context.Unwatch(terminated.Who);
                break;
            }

            return(Task.CompletedTask);
        }
        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();
        }