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

co.spraybot.messagerunner.couriers.DefaultCourier Maven / Gradle / Ivy

Go to download

A micro-framework to allow easily passing specific Vert.x messages to specific addresses for processing of those messages.

The newest version!
package co.spraybot.messagerunner.couriers;

import co.spraybot.messagerunner.Courier;
import co.spraybot.messagerunner.Parcel;
import co.spraybot.messagerunner.ProcessorAvailabilityParcel;
import co.spraybot.messagerunner.messagecodecs.ProcessorAvailabilityParcelMessageCodec;
import co.spraybot.messagerunner.parcels.DefaultProcessorAvailabilityParcel;
import io.vertx.core.*;
import io.vertx.core.eventbus.DeliveryOptions;
import io.vertx.core.eventbus.Message;

import javax.swing.text.html.Option;
import java.util.*;
import java.util.logging.Logger;

public class DefaultCourier extends AbstractVerticle implements Courier {

    @FunctionalInterface
    private interface ParcelHandler {
        void handle(Message messageParcel);
    }

    private class ParcelHandlerTuple {
        private Class parcelType;
        private ParcelHandler parcelHandler;

        public ParcelHandlerTuple(Class parcelType, ParcelHandler parcelHandler) {
            this.parcelType = parcelType;
            this.parcelHandler = parcelHandler;
        }

        public Class getParcelType() {
            return parcelType;
        }
    }

    private List parcelTypeHandlers = new ArrayList<>();
    private String address;

    public DefaultCourier(String address) {
        this.address = address;
        addProcessorAvailabilityParcelHandlerTuple();
    }

    private void addProcessorAvailabilityParcelHandlerTuple() {
        ParcelHandlerTuple availabilityHandlerTuple = new ParcelHandlerTuple(
            ProcessorAvailabilityParcel.class,
            availabilityMessage -> {
                ProcessorAvailabilityParcel availabilityParcel = (ProcessorAvailabilityParcel) availabilityMessage.body();

                if (availabilityParcel.isAvailable()) {
                    ParcelHandlerTuple parcelHandlerTuple = new ParcelHandlerTuple(
                        availabilityParcel.getParcelType(),
                        parcelProcessorHandler(availabilityParcel.getAddress())
                    );
                    parcelTypeHandlers.add(parcelHandlerTuple);
                } else {
                    parcelTypeHandlers.removeIf(tuple -> tuple.getParcelType().isAssignableFrom(availabilityParcel.getParcelType()));

                }
            }
        );
        parcelTypeHandlers.add(availabilityHandlerTuple);
    }

    private ParcelHandler parcelProcessorHandler(UUID processorAddress) {
        return _parcelMessage -> {
            DeliveryOptions options = new DeliveryOptions();
            options.setHeaders(_parcelMessage.headers());
            String eventBusAddress = processorAddress.toString();

            if (_parcelMessage.isSend()) {
                getVertx().eventBus().send(eventBusAddress, _parcelMessage.body(), options, asyncMessage -> {
                    _parcelMessage.reply(asyncMessage.result().body());
                });
            } else {
                getVertx().eventBus().publish(eventBusAddress, _parcelMessage.body(), options);
            }
        };
    }

    @Override
    public String getAddress() {
        return address;
    }

    @Override
    public void send(Message messageParcel) {
        Parcel parcel = messageParcel.body();
        Optional parcelHandler = findParcelHandler(parcel);

        if (parcelHandler.isPresent()) {
            parcelHandler.get().handle(messageParcel);
        } else {
            String msg = "Could not find a ParcelProcessor capable of handling " + parcel.getClass().getCanonicalName();
            messageParcel.fail(255, msg);
        }
    }

    private Optional findParcelHandler(Parcel parcel) {
        return parcelTypeHandlers.stream()
            .filter(tuple -> tuple.getParcelType().isAssignableFrom(parcel.getClass()))
            .map(tuple -> tuple.parcelHandler)
            .findFirst();
    }

    @Override
    public void start(Future future) {
        getVertx().eventBus().registerDefaultCodec(
            DefaultProcessorAvailabilityParcel.class,
            new ProcessorAvailabilityParcelMessageCodec()
        );
        getVertx().eventBus().consumer(getAddress(), message -> {
            Message parcelMessage = createMessageParcel(message);
            send(parcelMessage);
        }).completionHandler(future::complete);
    }

    private Message createMessageParcel(Message message) {
        return new Message() {
            @Override
            public String address() {
                return message.address();
            }

            @Override
            public MultiMap headers() {
                return message.headers();
            }

            @Override
            public Parcel body() {
                return (Parcel) message.body();
            }

            @Override
            public String replyAddress() {
                return message.replyAddress();
            }

            @Override
            public boolean isSend() {
                return message.isSend();
            }

            @Override
            public void reply(Object o) {
                message.reply(o);
            }

            @Override
            public  void reply(Object o, Handler>> handler) {
                message.reply(o, handler);
            }

            @Override
            public void reply(Object o, DeliveryOptions deliveryOptions) {
                message.reply(o, deliveryOptions);
            }

            @Override
            public  void reply(Object o, DeliveryOptions deliveryOptions, Handler>> handler) {
                message.reply(o, deliveryOptions, handler);
            }

            @Override
            public void fail(int i, String s) {
                message.fail(i, s);
            }
        };
    }

}