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

xin.bluesky.leiothrix.server.interactive.worker.msghandler.AcquireTaskHandler Maven / Gradle / Ivy

The newest version!
package xin.bluesky.leiothrix.server.interactive.worker.msghandler;

import com.alibaba.fastjson.JSON;
import io.netty.channel.ChannelHandlerContext;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xin.bluesky.leiothrix.model.msg.ServerMessage;
import xin.bluesky.leiothrix.model.msg.ServerMessageType;
import xin.bluesky.leiothrix.model.msg.WorkerMessage;
import xin.bluesky.leiothrix.model.task.partition.PartitionTask;
import xin.bluesky.leiothrix.model.task.partition.PartitionTaskWrapper;
import xin.bluesky.leiothrix.server.action.PartitionAllocatorFactory;
import xin.bluesky.leiothrix.server.action.PartitionTaskFinder;
import xin.bluesky.leiothrix.server.action.exception.NoTaskException;
import xin.bluesky.leiothrix.server.action.exception.WaitAndTryLaterException;
import xin.bluesky.leiothrix.server.bean.status.RangeStatus;
import xin.bluesky.leiothrix.server.cache.PartitionTaskContainer;
import xin.bluesky.leiothrix.server.interactive.worker.WorkerMessageHandler;
import xin.bluesky.leiothrix.server.lock.LockFactory;
import xin.bluesky.leiothrix.server.storage.RangeStorage;
import xin.bluesky.leiothrix.server.storage.TaskStorage;

import java.util.List;
import java.util.concurrent.TimeUnit;

import static xin.bluesky.leiothrix.model.task.partition.PartitionTaskWrapper.*;

/**
 * @author 张轲
 * worker.processor.threadnum.factor
 */
public class AcquireTaskHandler implements WorkerMessageHandler {

    private static final Logger logger = LoggerFactory.getLogger(AcquireTaskHandler.class);

    @Override
    public void handle(ChannelHandlerContext ctx, WorkerMessage message) {
        ServerMessage response = new ServerMessage();
        response.setType(ServerMessageType.ACQUIRE_TASK);

        String taskId = message.getData().toString();

        PartitionTaskContainer cache = PartitionTaskContainer.getInstance(taskId);
        PartitionTask partitionTask = cache.poll();

        if (partitionTask != null) {
            flushSuccessPartitionTask(ctx, response, taskId, partitionTask);
            return;
        }

        InterProcessMutex mutex = LockFactory.getPartitionTaskFindLock(taskId);
        boolean lockSuccess = false;

        try {
            lockSuccess = mutex.acquire(3, TimeUnit.SECONDS);
            if (lockSuccess && cache.isEmpty()) {
                PartitionTaskFinder finder = new PartitionTaskFinder(taskId, PartitionAllocatorFactory.get(taskId));
                List list = finder.find();
                cache.offer(list);
            }

            partitionTask = cache.poll();//这里一定能拿到的,如果没有任务,上面find的时候会抛出异常

            flushSuccessPartitionTask(ctx, response, taskId, partitionTask);
        } catch (Exception e) {
            flushNotSuccessPartitionTask(ctx, message, response, taskId, e);
        } finally {
            if (lockSuccess) {
                try {
                    mutex.release();
                } catch (Exception ex) {
                    logger.error(ex.getMessage(), ex);
                }
            }
        }
    }

    private void flushNotSuccessPartitionTask(ChannelHandlerContext ctx, WorkerMessage message, ServerMessage response, String taskId, Exception e) {
        PartitionTaskWrapper wrapper = handleException(taskId, e, response, message.getIp());
        response.setData(JSON.toJSONString(wrapper));
        ctx.writeAndFlush(JSON.toJSONString(response) + "\r\n");
    }

    private void flushSuccessPartitionTask(ChannelHandlerContext ctx, ServerMessage response, String taskId, PartitionTask partitionTask) {
        RangeStorage.setRangeStatus(taskId,
                partitionTask.getTableName(), partitionTask.getRangeName(), RangeStatus.PROCESSING);
        response.setData(JSON.toJSONString(new PartitionTaskWrapper(STATUS_SUCCESS, partitionTask)));
        ctx.writeAndFlush(JSON.toJSONString(response) + "\r\n");
    }

    private PartitionTaskWrapper handleException(String taskId, Exception e, ServerMessage response, String workerIp) {
        //设置该任务的当前资源已经足够了(因为其已拥有的资源也已经拿不到新任务片),以使得补偿线程不再对该任务分配新资源
        if (e instanceof NoTaskException) {
            TaskStorage.setResourceEnough(taskId, true);
            //todo: 怎么根据queue的消费情况,来置resourceEnough为false呢
            logger.info("worker[ip={}]请求新任务片,但当前没有可供其执行的任务.", workerIp);
            return new PartitionTaskWrapper(STATUS_NO_TASK, null);
        } else if (e instanceof WaitAndTryLaterException) {
            TaskStorage.setResourceEnough(taskId, true);
            logger.info("worker[ip={}]请求新任务片,但当前需要其等待并稍后重试.", workerIp);
            return new PartitionTaskWrapper(STATUS_WAIT_AND_TRY_LATER, null);
        } else {
            logger.error(e.getMessage(), e);
            return new PartitionTaskWrapper(STATUS_FAIL, null);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy