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

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

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

import com.devebot.opflow.exception.OpflowJsonTransformationException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author drupalex
 */
public class OpflowRpcRequest implements Iterator, OpflowTask.Timeoutable {
    private final static Logger LOG = LoggerFactory.getLogger(OpflowRpcRequest.class);
    private final OpflowLogTracer logTracer;
    private final String requestId;
    private final String routineId;
    private final long timeout;
    private final OpflowTask.Listener completeListener;
    private OpflowTask.TimeoutWatcher timeoutWatcher;
    private long timestamp;
    
    public OpflowRpcRequest(Map options, final OpflowTask.Listener completeListener) {
        Map opts = OpflowUtil.ensureNotNull(options);
        this.requestId = OpflowUtil.getRequestId(opts);
        this.routineId = OpflowUtil.getRoutineId(opts);
        if (opts.get("timeout") == null) {
            this.timeout = 0;
        } else if (opts.get("timeout") instanceof Long) {
            this.timeout = (Long)opts.get("timeout");
        } else if (opts.get("timeout") instanceof Integer) {
            this.timeout = ((Integer)opts.get("timeout")).longValue();
        } else {
            this.timeout = 0;
        }
        logTracer = OpflowLogTracer.ROOT.branch("requestId", requestId);
        this.completeListener = completeListener;
        if (Boolean.TRUE.equals(opts.get("watcherEnabled")) && completeListener != null && this.timeout > 0) {
            timeoutWatcher = new OpflowTask.TimeoutWatcher(requestId, this.timeout, new OpflowTask.Listener() {
                @Override
                public void handleEvent() {
                    OpflowLogTracer logWatcher = logTracer.copy();
                    if (OpflowLogTracer.has(LOG, "debug")) LOG.debug(logWatcher
                            .text("Request timeout event has been raised")
                            .stringify());
                    list.add(OpflowMessage.ERROR);
                    if (OpflowLogTracer.has(LOG, "debug")) LOG.debug(logWatcher
                            .text("Request raise completeListener (timeout)")
                            .stringify());
                    completeListener.handleEvent();
                }
            });
            timeoutWatcher.start();
        }
        checkTimestamp();
    }

    public String getRequestId() {
        return requestId;
    }
    
    public String getRoutineId() {
        return routineId;
    }

    @Override
    public long getTimeout() {
        if (this.timeout <= 0) return 0;
        return this.timeout;
    }
    
    @Override
    public long getTimestamp() {
        return this.timestamp;
    }
    
    @Override
    public void raiseTimeout() {
        this.push(OpflowMessage.ERROR);
    }
    
    private final BlockingQueue list = new LinkedBlockingQueue();
    private OpflowMessage current = null;
    
    @Override
    public boolean hasNext() {
        try {
            this.current = list.take();
            if (this.current == OpflowMessage.EMPTY) return false;
            if (this.current == OpflowMessage.ERROR) return false;
            return true;
        } catch (InterruptedException ie) {
            return false;
        }
    }

    @Override
    public OpflowMessage next() {
        OpflowMessage result = this.current;
        this.current = null;
        return result;
    }
    
    public void push(OpflowMessage message) {
        list.add(message);
        if (timeoutWatcher != null) {
            timeoutWatcher.check();
        }
        checkTimestamp();
        if(isDone(message)) {
            OpflowLogTracer pushTrail = logTracer.copy();
            if (OpflowLogTracer.has(LOG, "debug")) LOG.debug(pushTrail
                    .text("Request has completed/failed message")
                    .stringify());
            list.add(OpflowMessage.EMPTY);
            if (completeListener != null) {
                if (OpflowLogTracer.has(LOG, "debug")) LOG.debug(pushTrail
                        .text("Request raises completeListener (completed)")
                        .stringify());
                completeListener.handleEvent();
            }
            if (timeoutWatcher != null) {
                timeoutWatcher.close();
            }
        }
    }
    
    public List iterateResult() {
        List buff = new LinkedList();
        while(this.hasNext()) buff.add(this.next());
        return buff;
    }
    
    public OpflowRpcResult extractResult() {
        return extractResult(true);
    }
    
    public OpflowRpcResult extractResult(final boolean includeProgress) {
        OpflowLogTracer extractTrail = logTracer;
        if (OpflowLogTracer.has(LOG, "trace")) LOG.trace(extractTrail
                .text("Extracting result is running")
                .stringify());
        String workerTag = null;
        boolean failed = false;
        byte[] error = null;
        boolean completed = false;
        byte[] value = null;
        List steps = new LinkedList();
        while(this.hasNext()) {
            OpflowMessage msg = this.next();
            String status = getStatus(msg);
            if (OpflowLogTracer.has(LOG, "trace")) LOG.trace(extractTrail
                    .put("status", status)
                    .text("Extracting result receives a message")
                    .stringify());
            if (status == null) continue;
            if ("progress".equals(status)) {
                if (includeProgress) {
                    try {
                        int percent = OpflowJsontool.extractFieldAsInt(msg.getBodyAsString(), "percent");
                        steps.add(new OpflowRpcResult.Step(percent));
                    } catch (OpflowJsonTransformationException jse) {
                        steps.add(new OpflowRpcResult.Step());
                    }
                }
            } else
            if ("failed".equals(status)) {
                workerTag = OpflowUtil.getMessageField(msg, "workerTag");
                failed = true;
                error = msg.getBody();
            } else
            if ("completed".equals(status)) {
                workerTag = OpflowUtil.getMessageField(msg, "workerTag");
                completed = true;
                value = msg.getBody();
            }
        }
        if (OpflowLogTracer.has(LOG, "trace")) LOG.trace(extractTrail
                .text("Extracting result has completed")
                .stringify());
        if (!includeProgress) steps = null;
        return new OpflowRpcResult(routineId, requestId, workerTag, steps, failed, error, completed, value);
    }
    
    private static final List STATUS = Arrays.asList(new String[] { "failed", "completed" });
    
    private boolean isDone(OpflowMessage message) {
        String status = getStatus(message);
        if (status == null) return false;
        return STATUS.indexOf(status) >= 0;
    }
    
    private void checkTimestamp() {
        timestamp = OpflowUtil.getCurrentTime();
    }
    
    public static String getStatus(OpflowMessage message) {
        return OpflowUtil.getMessageField(message, "status");
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy