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

com.devebot.opflow.OpflowRpcWorker Maven / Gradle / Ivy

There is a newer version: 0.3.1
Show newest version
package com.devebot.opflow;

import com.devebot.opflow.exception.OpflowBootstrapException;
import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author drupalex
 */
public class OpflowRpcWorker {
    private final static Logger LOG = LoggerFactory.getLogger(OpflowRpcWorker.class);
    private final OpflowLogTracer logTracer;
    
    private final OpflowEngine engine;
    private final OpflowExecutor executor;
    private final String operatorName;
    private final String responseName;
    
    public OpflowRpcWorker(Map params) throws OpflowBootstrapException {
        params = OpflowUtil.ensureNotNull(params);
        
        final String rpcWorkerId = OpflowUtil.getOptionField(params, "rpcWorkerId", true);
        logTracer = OpflowLogTracer.ROOT.branch("rpcWorkerId", rpcWorkerId);
        
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logTracer
                .text("RpcWorker[${rpcWorkerId}].new()")
                .stringify());
        
        Map brokerParams = new HashMap();
        OpflowUtil.copyParameters(brokerParams, params, OpflowEngine.PARAMETER_NAMES);
        brokerParams.put("engineId", rpcWorkerId);
        brokerParams.put("mode", "rpc_worker");
        brokerParams.put("exchangeType", "direct");
        
        operatorName = (String) params.get("operatorName");
        responseName = (String) params.get("responseName");
        
        if (operatorName != null && responseName != null && operatorName.equals(responseName)) {
            throw new OpflowBootstrapException("operatorName should be different with responseName");
        }
        
        engine = new OpflowEngine(brokerParams);
        executor = new OpflowExecutor(engine);
        
        if (operatorName != null) {
            executor.assertQueue(operatorName);
        }
        
        if (responseName != null) {
            executor.assertQueue(responseName);
        }
        
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logTracer
                .put("operatorName", operatorName)
                .put("responseName", responseName)
                .tags("RpcWorker.new() parameters")
                .text("RpcWorker[${rpcWorkerId}].new() operatorName: '${operatorName}', responseName: '${responseName}'")
                .stringify());
        
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logTracer
                .text("RpcWorker[${rpcWorkerId}].new() end!")
                .stringify());
    }

    private OpflowEngine.ConsumerInfo consumerInfo;
    private List middlewares = new LinkedList();
    
    public OpflowEngine.ConsumerInfo process(final OpflowRpcListener listener) {
        return process(TRUE, listener);
    }

    public OpflowEngine.ConsumerInfo process(final String routineId, final OpflowRpcListener listener) {
        return process(new Checker() {
            @Override
            public boolean match(String originRoutineId) {
                return routineId != null && routineId.equals(originRoutineId);
            }
        }, listener);
    };
    
    public OpflowEngine.ConsumerInfo process(final String[] routineIds, final OpflowRpcListener listener) {
        return process(new Checker() {
            @Override
            public boolean match(String originRoutineId) {
                return routineIds != null && OpflowUtil.arrayContains(routineIds, originRoutineId);
            }
        }, listener);
    };
    
    public OpflowEngine.ConsumerInfo process(final Set routineIds, final OpflowRpcListener listener) {
        return process(new Checker() {
            @Override
            public boolean match(String originRoutineId) {
                return routineIds != null && routineIds.contains(originRoutineId);
            }
        }, listener);
    };
    
    public OpflowEngine.ConsumerInfo process(Checker checker, final OpflowRpcListener listener) {
        final String _consumerId = OpflowUtil.getLogID();
        final OpflowLogTracer logProcess = logTracer.branch("consumerId", _consumerId);
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logProcess
                .text("Consumer[${consumerId}] - RpcWorker[${rpcWorkerId}].process() is invoked")
                .stringify());
        
        if (checker != null && listener != null) {
            middlewares.add(new Middleware(checker, listener));
        }
        if (consumerInfo != null) return consumerInfo;
        consumerInfo = engine.consume(new OpflowListener() {
            @Override
            public boolean processMessage(byte[] body, AMQP.BasicProperties properties, 
                    String queueName, Channel channel, String workerTag) throws IOException {
                OpflowMessage request = new OpflowMessage(body, properties.getHeaders());
                OpflowRpcResponse response = new OpflowRpcResponse(channel, properties, workerTag, queueName);
                String routineId = OpflowUtil.getRoutineId(properties.getHeaders(), false);
                String requestId = OpflowUtil.getRequestId(properties.getHeaders(), false);

                OpflowLogTracer logRequest = null;
                if (OpflowLogTracer.has(LOG, "info")) logRequest = logProcess.branch("requestId", requestId);

                if (OpflowLogTracer.has(LOG, "info") && logRequest != null) LOG.info(logRequest
                        .put("routineId", routineId)
                        .text("Request[${requestId}] - Consumer[${consumerId}] receives a new RPC request")
                        .stringify());
                int count = 0;
                for(Middleware middleware : middlewares) {
                    if (middleware.getChecker().match(routineId)) {
                        count++;
                        Boolean nextAction = middleware.getListener().processMessage(request, response);
                        if (nextAction == null || nextAction == OpflowRpcListener.DONE) break;
                    }
                }
                if (OpflowLogTracer.has(LOG, "info") && logRequest != null) LOG.info(logRequest
                        .text("Request[${requestId}] - RPC request processing has completed")
                        .stringify());
                return count > 0;
            }
        }, OpflowUtil.buildMap(new OpflowUtil.MapListener() {
            @Override
            public void transform(Map opts) {
                opts.put("consumerId", _consumerId);
                opts.put("queueName", operatorName);
                opts.put("replyTo", responseName);
                opts.put("binding", Boolean.TRUE);
            }
        }).toMap());
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logProcess
                .text("Consumer[${consumerId}] - process() has completed")
                .stringify());
        return consumerInfo;
    }
    
    public class State extends OpflowEngine.State {
        public State(OpflowEngine.State superState) {
            super(superState);
        }
    }
    
    public State check() {
        State state = new State(engine.check());
        return state;
    }
    
    public void close() {
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logTracer
                .text("RpcWorker[${rpcWorkerId}].close()")
                .stringify());
        if (engine != null) {
            engine.cancelConsumer(consumerInfo);
            engine.close();
        }
        if (OpflowLogTracer.has(LOG, "info")) LOG.info(logTracer
                .text("RpcWorker[${rpcWorkerId}].close() has completed")
                .stringify());
    }

    public OpflowExecutor getExecutor() {
        return executor;
    }

    public String getOperatorName() {
        return operatorName;
    }

    public String getResponseName() {
        return responseName;
    }
    
    public class Middleware {
        private final Checker checker;
        private final OpflowRpcListener listener;

        public Middleware(Checker checker, OpflowRpcListener listener) {
            this.checker = checker;
            this.listener = listener;
        }

        public Checker getChecker() {
            return checker;
        }

        public OpflowRpcListener getListener() {
            return listener;
        }
    }
    
    public interface Checker {
        public boolean match(String routineId);
    }
    
    private final Checker TRUE = new Checker() {
        @Override
        public boolean match(String routineId) {
            return true;
        }
    };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy