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

org.bdware.doip.event.MultiTopicPersistencePublisher Maven / Gradle / Ivy

The newest version!
package org.bdware.doip.event;

import com.google.gson.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.doip.audit.client.AuditDoipClient;
import org.bdware.doip.audit.writer.AuditConfig;
import org.bdware.doip.audit.writer.AuditRepo;
import org.bdware.doip.audit.writer.AuditType;
import org.bdware.doip.codec.doipMessage.DoipMessage;
import org.bdware.doip.codec.doipMessage.DoipMessageFactory;
import org.bdware.doip.codec.doipMessage.DoipResponseCode;
import org.bdware.doip.codec.exception.DoipConnectException;
import org.bdware.doip.endpoint.client.ClientConfig;
import org.bdware.doip.endpoint.client.DoipClient;
import org.bdware.doip.endpoint.event.PublishMessageType;
import org.bdware.doip.endpoint.event.Publisher;

import java.nio.charset.StandardCharsets;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiTopicPersistencePublisher implements Publisher {
    private static final Gson GSON = new Gson();
    // key 是topicId, value是[subscriber1,subscriber2,...]
    // support only one topicId!
    // key  =
    KVStore topicToSubscribers;
    MultiTagColumnStorage topicToMessages;
    DoipClient client;
    static Logger LOGGER = LogManager.getLogger(MultiTopicPersistencePublisher.class);
    Map cachedClient;
    ExecutorService threadPool = Executors.newFixedThreadPool(20);

    public MultiTopicPersistencePublisher(KVStore topicToSubscriber, MultiTagColumnStorage messageStorage, DoipClient client) {
        this.topicToSubscribers = topicToSubscriber;
        this.topicToMessages = messageStorage;
        this.client = client;
        cachedClient = new ConcurrentHashMap<>();
    }


    synchronized private void addSubscribers(String topicId, String subscriberId) {
        JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
        JsonPrimitive sid = new JsonPrimitive(subscriberId);
        if (!subscribers.contains(sid)) {
            subscribers.add(sid);
            topicToSubscribers.put(topicId, subscribers.toString());
        }
    }

    synchronized private void removeSubscribers(String topicId, String subscriberId) {
        JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
        JsonPrimitive sid = new JsonPrimitive(subscriberId);
        if (subscribers.contains(sid)) {
            subscribers.remove(sid);
            topicToSubscribers.put(topicId, subscribers.toString());
        }
    }

    private JsonElement getSubscribersAsJson(String key, JsonElement defaultValue) {
        String content = topicToSubscribers.get(key);
        try {
            if (null != content && !content.isEmpty()) {
                return JsonParser.parseString(content);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return defaultValue;
    }

    private DoipClient getOrCreateConnection(String subscriberId) {
        if (subscriberId.startsWith("tcp://")) {
            return getTcpDirectlyClient(subscriberId);
        }
        return client;
    }

    private DoipClient getTcpDirectlyClient(String uri) {
        DoipClient client1 = cachedClient.get(uri);
        if (client1 != null) {
            if (!client1.isConnected()) {
                try {
                    client1.reconnect();
                } catch (DoipConnectException e) {
                    throw new RuntimeException(e);
                }
            }
            return client1;
        }
        client1 = new AuditDoipClient(AuditConfig.newInstance(new AuditRepo(null, null), AuditType.None, null), null);
        client1.connect(ClientConfig.fromUrl(uri));
        cachedClient.put(uri, client1);
        return client1;
    }

    @Override
    public DoipMessage subscribe(String topicId, String subscriberId, boolean needReplay, DoipMessage request) {
        addSubscribers(topicId, subscriberId);
        long total = topicToMessages.size(topicId);
        if (needReplay) {
            threadPool.execute(() -> {
                DoipClient client = getOrCreateConnection(subscriberId);
                try {
                    for (int i = 0; i < total; i++) {
                        String msg = topicToMessages.get(topicId, i);
                        DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
                        client.sendRawMessage(message, null);
                    }
                } catch (Exception ignored) {
                }
            });
        }
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        builder.createResponse(DoipResponseCode.Success, request).setBody((total + "").getBytes());
        return builder.create();
    }

    @Override
    public DoipMessage unsubscribe(String topicId, String subscriberId, DoipMessage request) {
        removeSubscribers(topicId, subscriberId);
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
        return builder.create();
    }

    @Override
    public DoipMessage sendDataInRange(String topicId, String subscriberId, long offset, long count, DoipMessage request) {
        //TODO检查一下是不是在我列表里?
        threadPool.execute(() -> {
            DoipClient client = getOrCreateConnection(subscriberId);
            try {
                for (long i = offset; i < offset + count; i++) {
                    String msg = topicToMessages.get(topicId, i);
                    DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
                    message.header.parameters.id = subscriberId;
                    client.sendRawMessage(message, null);
                }
            } catch (Exception ignored) {
            }
        });
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
        return builder.create();
    }

    @Override
    public DoipMessage sendDataInList(String topicId, String subscriberId, JsonArray indexList, DoipMessage request) {
        //TODO检查一下是不是在我列表里?
        threadPool.execute(() -> {
            DoipClient client = getOrCreateConnection(subscriberId);
            try {
                for (JsonElement je : indexList) {
                    long i = je.getAsLong();
                    String msg = topicToMessages.get(topicId, i);
                    DoipMessage message = GSON.fromJson(msg, DoipMessage.class);
                    message.header.parameters.id = subscriberId;
                    client.sendRawMessage(message, null);
                }
            } catch (Exception ignored) {
            }
        });
        DoipMessageFactory.DoipMessageBuilder builder = new DoipMessageFactory.DoipMessageBuilder();
        builder.createResponse(DoipResponseCode.Success, request).setBody("success".getBytes(StandardCharsets.UTF_8));
        return builder.create();
    }

    @Override
    public DoipMessage verifyMerkelInRange(String topicId, String subscriberId, DoipMessage request) {
        throw new IllegalStateException("unsupported message type");
    }

    @Override
    public DoipMessage sendMerkelInRange(String topicId, String subscriberId, DoipMessage request) {
        throw new IllegalStateException("unsupported message type");
    }


    @Override
    public void publish(String topicId, DoipMessage request) {
        JsonArray subscribers = getSubscribersAsJson(topicId, new JsonArray()).getAsJsonArray();
        request.header.parameters.attributes.addProperty("topicId", topicId);
        request.header.parameters.attributes.addProperty("publishType", PublishMessageType.Data.name());
        topicToMessages.put(topicId, GSON.toJson(request));
        threadPool.execute(() -> {
            Set sent = new HashSet<>();
            subscribers.forEach(je -> {
                String id = je.getAsString();
                DoipClient client = getOrCreateConnection(id);
                DoipMessage tosend = request.withNewDOID(request, je.getAsString());
                try {
                    if (!sent.contains(id)) {
                        sent.add(id);
                        client.sendRawMessage(tosend, null);
                    }
                } catch (Exception e) {
                    try {
                        client.reconnect();
                    } catch (DoipConnectException ex) {
                        throw new RuntimeException(ex);
                    }
                }
            });
        });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy