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

org.fisco.bcos.sdk.eventsub.EventSubscribeImp Maven / Gradle / Ivy

There is a newer version: 2.7.0
Show newest version
/*
 * Copyright 2014-2020  [fisco-dev]
 *
 * 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 org.fisco.bcos.sdk.eventsub;

import com.fasterxml.jackson.core.JsonProcessingException;
import java.math.BigInteger;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.fisco.bcos.sdk.channel.Channel;
import org.fisco.bcos.sdk.channel.ResponseCallback;
import org.fisco.bcos.sdk.eventsub.filter.EventLogFilter;
import org.fisco.bcos.sdk.eventsub.filter.EventLogFilterStatus;
import org.fisco.bcos.sdk.eventsub.filter.EventLogResponse;
import org.fisco.bcos.sdk.eventsub.filter.EventPushMsgHandler;
import org.fisco.bcos.sdk.eventsub.filter.EventSubNodeRespStatus;
import org.fisco.bcos.sdk.eventsub.filter.FilterManager;
import org.fisco.bcos.sdk.eventsub.filter.ScheduleTimeConfig;
import org.fisco.bcos.sdk.model.*;
import org.fisco.bcos.sdk.service.GroupManagerService;
import org.fisco.bcos.sdk.utils.ObjectMapperFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class EventSubscribeImp implements EventSubscribe {
    private static final Logger logger = LoggerFactory.getLogger(EventSubscribeImp.class);
    private Channel channel;
    private GroupManagerService groupManagerService;
    private Integer groupId;
    private FilterManager filterManager;
    private EventPushMsgHandler msgHander;
    private EventResource eventResource;
    private boolean running = false;
    ScheduledThreadPoolExecutor resendSchedule = new ScheduledThreadPoolExecutor(1);

    public EventSubscribeImp(
            GroupManagerService groupManagerService, EventResource eventResource, Integer groupId) {
        this.channel = groupManagerService.getChannel();
        this.groupManagerService = groupManagerService;
        this.groupId = groupId;
        this.eventResource = eventResource;
        filterManager = eventResource.getFilterManager();
        msgHander = eventResource.getMsgHander();
        channel.addMessageHandler(MsgType.EVENT_LOG_PUSH, msgHander);
        channel.addDisconnectHandler(msgHander);
    }

    @Override
    public EventResource getEventResource() {
        return eventResource;
    }

    @Override
    public String subscribeEvent(EventLogParams params, EventCallback callback) {
        BigInteger number = groupManagerService.getLatestBlockNumberByGroup(groupId);
        logger.info(" subscribe event at block num:" + number);
        if (!params.checkParams(number)) {
            callback.onReceiveLog(EventSubNodeRespStatus.INVALID_PARAMS.getStatus(), null);
            return null;
        }
        EventLogFilter filter = new EventLogFilter();
        filter.setRegisterID(EventSubscribe.newSeq());
        filter.setParams(params);
        filter.setCallback(callback);
        filterManager.addFilter(filter);
        sendFilter(filter);

        logger.info(
                " subscribe event, registerID: {}, filterID : {}",
                filter.getRegisterID(),
                filter.getFilterID());
        return filter.getRegisterID();
    }

    @Override
    public void unsubscribeEvent(String registerID, EventCallback callback) {
        EventLogFilter filter = filterManager.getFilter(registerID);
        if (filter == null) {
            logger.info(" try to unsubscribe an nonexistent event");
            return;
        }
        // update callback to handle unsubscribe result
        filter.setCallback(callback);
        filterManager.addCallback(filter.getFilterID(), callback);

        // send message to unsubscribe event
        Message msg = new Message();
        msg.setSeq(EventSubscribe.newSeq());
        msg.setType(Short.valueOf((short) MsgType.CLIENT_UNREGISTER_EVENT_LOG.getType()));
        msg.setResult(0);
        try {
            String content =
                    filter.getParamJsonString(String.valueOf(groupId), filter.getFilterID());
            logger.info(
                    " unsubscribe event, registerID: {}, filterID : {}",
                    filter.getRegisterID(),
                    filter.getFilterID());
            msg.setData(content.getBytes());
        } catch (JsonProcessingException e) {
            logger.error(" unsubscribe event error: {}", e.getMessage());
        }

        EventMsg eventMsg = new EventMsg(msg);
        eventMsg.setTopic("");
        eventMsg.setData(msg.getData());
        this.groupManagerService.asyncSendMessageToGroup(
                groupId, eventMsg, new UnRegisterEventSubRespCallback(filterManager, filter));
    }

    @Override
    public List getAllSubscribedEvent() {
        return filterManager.getAllSubscribedEvent();
    }

    @Override
    public void start() {
        if (running) {
            return;
        }
        running = true;
        resendSchedule.scheduleAtFixedRate(
                () -> {
                    resendWaitingFilters();
                },
                0,
                ScheduleTimeConfig.resendFrequency,
                TimeUnit.MILLISECONDS);
    }

    @Override
    public void stop() {
        if (!running) {
            return;
        }
        running = false;
        resendSchedule.shutdown();
        // unsubscribe events, fisco bcos 2.7.0
        /*List filterList = getAllSubscribedEvent();
        for (EventLogFilter filter : filterList) {
            EventCallback callback =
                    new EventCallback() {
                        @Override
                        public void onReceiveLog(int status, List logs) {
                            logger.info(
                                    "unsubscribe event registerId : {}, result : {}",
                                    filter.getRegisterID(),
                                    status);
                        }
                    };
            unsubscribeEvent(filter.getRegisterID(), callback);
        }*/
    }

    private void resendWaitingFilters() {
        List filters = filterManager.getWaitingReqFilters();
        try {
            for (EventLogFilter filter : filters) {
                sendFilter(filter);
            }
            logger.info("Resend waiting filters, size: {}", filters.size());
        } catch (Exception e) {
            logger.error("resendWaitingFilters exception : {}", e.getMessage());
            for (EventLogFilter filter : filters) {
                filter.setStatus(EventLogFilterStatus.WAITING_REQUEST);
            }
        }
    }

    private void sendFilter(EventLogFilter filter) {
        Message msg = new Message();
        msg.setSeq(EventSubscribe.newSeq());
        msg.setType(Short.valueOf((short) MsgType.CLIENT_REGISTER_EVENT_LOG.getType()));
        msg.setResult(0);
        try {
            String content = filter.getNewParamJsonString(String.valueOf(groupId));
            msg.setData(content.getBytes());
        } catch (JsonProcessingException e) {
            logger.error(
                    "send filter error and remove bad filter, registerID: {},filterID : {}, error: {}",
                    filter.getRegisterID(),
                    filter.getFilterID(),
                    e.getMessage());
            filterManager.removeFilter(filter.getRegisterID());
        }

        filterManager.addCallback(filter.getFilterID(), filter.getCallback());
        EventMsg eventMsg = new EventMsg(msg);
        eventMsg.setTopic("");
        eventMsg.setData(msg.getData());
        this.groupManagerService.asyncSendMessageToGroup(
                groupId,
                eventMsg,
                new RegisterEventSubRespCallback(
                        filterManager, filter, filter.getFilterID(), filter.getRegisterID()));
    }

    class RegisterEventSubRespCallback extends ResponseCallback {
        FilterManager filterManager;
        EventLogFilter filter;
        String filterID;
        String registerID;

        public RegisterEventSubRespCallback(
                FilterManager filterManager,
                EventLogFilter filter,
                String filterID,
                String registerID) {
            this.filterManager = filterManager;
            this.filter = filter;
            this.filterID = filterID;
            this.registerID = registerID;
        }

        @Override
        public void onResponse(Response response) {
            logger.info(
                    " event filter callback response, registerID: {}, filterID: {}, seq: {}, error code: {},  content: {}",
                    registerID,
                    filterID,
                    response.getMessageID(),
                    response.getErrorCode(),
                    response.getContent());
            try {
                if (0 == response.getErrorCode()) {
                    EventLogResponse resp =
                            ObjectMapperFactory.getObjectMapper()
                                    .readValue(
                                            response.getContent().trim(), EventLogResponse.class);
                    if (resp.getResult() == 0) {
                        // node give an "OK" response, event log will be pushed soon
                        filterManager.updateFilterStatus(
                                filter, EventLogFilterStatus.EVENT_LOG_PUSHING, response.getCtx());
                        logger.info(
                                " filter {} status changed to EVENT_LOG_PUSHING",
                                filter.getFilterID());
                    } else {
                        // node give a bad response, will not push event log, trigger callback
                        filterManager.removeFilter(registerID);
                        filterManager.removeCallback(filterID);
                    }
                    filter.getCallback().onReceiveLog(resp.getResult(), null);
                } else {
                    filterManager.updateFilterStatus(
                            filter, EventLogFilterStatus.WAITING_REQUEST, null);
                    filterManager.removeCallback(filterID);
                }
            } catch (Exception e) {
                logger.error(
                        " event filter response message exception, filterID: {}, registerID: {}, exception message: {}",
                        filterID,
                        registerID,
                        e.getMessage());
                filter.getCallback()
                        .onReceiveLog(EventSubNodeRespStatus.OTHER_ERROR.getStatus(), null);
                filterManager.removeFilter(registerID);
                filterManager.removeCallback(filterID);
            }
        }
    }

    class UnRegisterEventSubRespCallback extends ResponseCallback {
        FilterManager filterManager;
        EventLogFilter filter;

        public UnRegisterEventSubRespCallback(FilterManager filterManager, EventLogFilter filter) {
            this.filterManager = filterManager;
            this.filter = filter;
        }

        @Override
        public void onResponse(Response response) {
            String registerId = filter.getRegisterID();
            logger.info(
                    " unregister event callback response, registerID: {}, seq: {}, error code: {}, content: {}",
                    registerId,
                    response.getMessageID(),
                    response.getErrorCode(),
                    response.getContent());
            try {
                if (0 == response.getErrorCode()) {
                    EventLogResponse resp =
                            ObjectMapperFactory.getObjectMapper()
                                    .readValue(
                                            response.getContent().trim(), EventLogResponse.class);
                    if (resp.getResult() == 0) {
                        // node give an "OK" response, event log will be deleted
                        logger.info(" unregister event success");
                        filterManager.removeFilter(filter.getRegisterID());
                        filterManager.removeCallback(filter.getFilterID());
                    } else {
                        logger.warn(" unregister event fail");
                    }
                    filter.getCallback().onReceiveLog(resp.getResult(), null);
                }
            } catch (Exception e) {
                logger.error(
                        " unregister event response message exception, registerID: {}, exception message: {}",
                        registerId,
                        e.getMessage());
                filter.getCallback()
                        .onReceiveLog(EventSubNodeRespStatus.OTHER_ERROR.getStatus(), null);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy