All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.e6tech.elements.network.cluster.messaging.Messenger Maven / Gradle / Ivy

There is a newer version: 2.7.9
Show newest version
/*
 * Copyright 2015-2019 Futeh Kao
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package net.e6tech.elements.network.cluster.messaging;

import akka.actor.PoisonPill;
import akka.actor.Status;
import akka.actor.typed.ActorRef;
import akka.actor.typed.Behavior;
import akka.actor.typed.PostStop;
import akka.actor.typed.javadsl.Adapter;
import akka.actor.typed.javadsl.Behaviors;
import akka.cluster.pubsub.DistributedPubSub;
import akka.cluster.pubsub.DistributedPubSubMediator;
import net.e6tech.elements.common.actor.typed.Receptor;
import net.e6tech.elements.common.actor.typed.Typed;
import net.e6tech.elements.common.resources.NotAvailableException;
import net.e6tech.elements.common.subscribe.Subscriber;

import java.util.HashMap;
import java.util.Map;

import static net.e6tech.elements.network.cluster.messaging.MessagingEvents.*;

@SuppressWarnings("unchecked")
public class Messenger extends Receptor {

    private static final String SUBSCRIBER_PREFIX = "subscriber-";
    private static final String DESTINATION_PREFIX = "destination-";

    // activate the extension
    private akka.actor.ActorRef mediator;
    private Map> subscribers = new HashMap<>();
    private Map destinations = new HashMap<>();

    @Override
    public void initialize() {
        mediator = DistributedPubSub.lookup().get(untypedContext().system()).mediator();
    }

    @Typed
    private void postStop(PostStop postStop) {
        for (Map map : subscribers.values()) {
            for (ActorRef ref : map.values()) {
                ref.tell(PoisonPill.getInstance());
            }
        }
        subscribers.clear();

        for (ActorRef ref : destinations.values()) {
            ref.tell(PoisonPill.getInstance());
        }
        destinations.clear();
    }

    @Typed
    private void subscribe(Subscribe event) {
        Map map = subscribers.computeIfAbsent(event.topic, topic -> new HashMap<>());
        map.computeIfAbsent(event.subscriber,
                sub -> childActor(SubscriberActor.class)
                .withName(SUBSCRIBER_PREFIX + event.topic + System.identityHashCode(event.subscriber))
                .spawn(new SubscriberActor(event.topic, event.subscriber)));
    }

    @Typed
    private void unsubscribe(Unsubscribe event) {
        Map map = subscribers.get(event.topic);
        if (map != null) {
            ActorRef child = map.get(event.subscriber);
            if (child != null) {
                mediator.tell(new DistributedPubSubMediator.Unsubscribe(event.topic, Adapter.toClassic(child)), untypedRef());
                child.tell(PoisonPill.getInstance());
                map.remove(event.subscriber);
            }
        }
    }

    @Typed
    private Behavior newDestination(NewDestination event) {
        if (destinations.get(event.destination) != null) {
            event.getSender().tell(new Status.Failure(new NotAvailableException("Service not available.")));
        } else {
            ActorRef dest = this.childActor(Destination.class)
                    .withName(DESTINATION_PREFIX + event.destination)
                    .spawn((new Destination(event.subscriber)));
            destinations.put(event.destination, dest);
        }
        return Behaviors.same();
    }

    @Typed
    private void removeDestination(RemoveDestination event) {
        ActorRef child = destinations.get(event.destination);
        if (child != null) {
            mediator.tell(new DistributedPubSubMediator.Remove(child.path().name()), untypedRef());
            child.tell(PoisonPill.getInstance());
            destinations.remove("/user/" + getSelf().path().name() + "/" + DESTINATION_PREFIX + event.destination);
        }
    }

    @Typed
    private void publish(Publish event) {
        mediator.tell(new DistributedPubSubMediator.Publish(event.getTopic(), event), untypedRef());
    }

    @Typed
    private void send(Send event) {
        mediator.tell(new DistributedPubSubMediator.Send("/user/" + getSelf().path().name() + "/" + DESTINATION_PREFIX + event.destination,
                event, true), untypedRef());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy