Package com.level3.meanwhile.concurrent

Source Code of com.level3.meanwhile.concurrent.MeanwhileRunner

package com.level3.meanwhile.concurrent;

import com.level3.meanwhile.TaskQueue;
import com.level3.meanwhile.Chain;
import com.level3.meanwhile.state.ClaimCheck;
import com.level3.meanwhile.Stage;
import com.level3.meanwhile.Task;
import com.level3.meanwhile.state.TaskStatus;
import java.util.ArrayList;
import java.util.List;


/**
* MeanwhileRunner wraps a Task and manages the Task's execution throughout its life cycle.
*
*
*
* @author Jonathan Griggs <Jonathan.Griggs@Level3.com>
* @since 0.2
*/
public final class MeanwhileRunner<T extends Task> implements Runnable {   
    /*
     * The wrapped Task
     */
    private T task;
    private ClaimCheck claimCheck;
    private TaskQueue manager;
    private boolean cancelledInFlight = false;
    private List<MeanwhileFuture<T>> futures = new ArrayList<MeanwhileFuture<T>>();
   
    /**
     * The default status of a Task is DEQUEUED
     * @see TaskStatus
     */
    private TaskStatus status = TaskStatus.DEQUEUED;
   
    public MeanwhileRunner(final T task, final TaskQueue manager) {
        this.manager = manager;
        claimCheck = new ClaimCheck(task.getUUID());
        init(task);
    }
   
    public MeanwhileRunner(final T task, final TaskQueue manager, final ClaimCheck parentCheck) {
        this.manager = manager;
        claimCheck = new ClaimCheck(task.getUUID(),parentCheck);
        init(task);
    }
   
   
    private void init(T task) {
        this.task = task;
        status = TaskStatus.QUEUED;
        task.onSubmit();
    }
   
    public List<MeanwhileFuture<T>> submitChainedTasks() {
        List<MeanwhileFuture<T>> chainFutures = new ArrayList<MeanwhileFuture<T>>();
        if(task instanceof Chain) {
            for(Task nextTask : ((Chain)task).getChainedTasks()) {
                chainFutures.add(manager.submit(new MeanwhileRunner(nextTask,manager,claimCheck)));
            }
        }
        return chainFutures;
    }
   
    public List<MeanwhileFuture> getStageFutures() {
        List<MeanwhileFuture> futures = new ArrayList<MeanwhileFuture>();
        if(task instanceof Stage) {
            for(Task nextTask : ((Stage)task).getStagedTasks()) {
                futures.add(manager.submit(new MeanwhileRunner(nextTask,manager,claimCheck)));
            }
        }      
        return futures;
    }
   
    /**
     * The {@code run()} implementation required to satisfy the Runnable interface.
     *
     * <p>Calls {@code Task.execute()} and performs logic for determining the success or failure of the Task
     *
     * @see Runnable
     * @since 0.1
     */
    public final void run() {
            try {
                boolean success = true;
                do {
                    if(TaskStatus.RETRY.equals(status) == true) {
                        task.onRetry();
                    }
                    status = TaskStatus.WORKING;
                    task.onStart();
                    if(task instanceof Stage) {
                        for(MeanwhileFuture<Task> future : getStageFutures()) {
                            future.get();
                            if(!future.isSuccess()) {
                                success = false;
                            }
                        } 
                    } else {
                        success = task.execute();
                    }
                    if(!success && task.retryOnFail()) {
                        status = TaskStatus.RETRY;
                    }
                } while (!success && TaskStatus.RETRY.equals(status));
               
                if(success) {
                    status = TaskStatus.SUCCESS;
                    task.onSuccess();
                } else {
                    status = TaskStatus.FAILED;
                    task.onFailure();
                }
            } catch(Throwable e) {
                status = TaskStatus.FAILED;
                task.onFailure();
            } finally {
                task.onComplete();
            }
            if(TaskStatus.SUCCESS.equals(this.getStatus())&&!cancelledInFlight) {
                futures = submitChainedTasks();
            } else if(TaskStatus.SUCCESS.equals(this.getStatus())&&cancelledInFlight) {
                if(task instanceof Chain) {
                    for(Task nextTask : ((Chain)task).getChainedTasks()) {
                        nextTask.onCancel();
                    }
                }
            }
    }
   
    public boolean cancel() {
        boolean canceled = false;
        if(TaskStatus.QUEUED.equals(this.getStatus())) {
            task.onCancel();
            canceled = true;
        } else if (TaskStatus.WORKING.equals(this.getStatus())) {
            cancelledInFlight = true;
            if(task instanceof Chain) {
                if(((Chain)task).getChainedTasks().size()>0) {
                    canceled = true;
                }
            }
        }
        return canceled;
    }

    /**
     * @return the task
     */
    public Task getTask() {
        return task;
    }

    /**
     * @return the status
     */
    public TaskStatus getStatus() {
        return status;
    }
   
    public boolean isSuccess() {
        if(!TaskStatus.SUCCESS.equals(status)) {
            return false;
        } else if (!futures.isEmpty()) {
            for(MeanwhileFuture future : futures) {
                if(!future.isSuccess()) {
                    return false;
                }
            }
        }
        return true;
    }
   
    /**
    *
    * Gets the ClaimCheck of the wrapped task
    *
    * @return ClaimCheck representing this Task
    * @since 0.1
    */
    public ClaimCheck getClaimCheck() {
        return claimCheck;
    }
   
    /**
    * Returns the hashCode of the Task
    *
    * @see ClaimCheck#hashCode
    * @since 0.1
    */
    @Override
    public int hashCode() {
        return claimCheck.hashCode();
    }

    /**
     * Equals depends on the Task's ClaimCheck - in fact, you can pass a ClaimCheck (or UUID obj or UUID String) and it can equal the Task object
     *
     * @see ClaimCheck#equals
     * @since 0.1
     */
    @Override
    public boolean equals(final Object obj) {
        if (this == obj)
            return true;       
        return claimCheck.equals(obj);
    }

    /**
     * @return the futures
     */
    public List<MeanwhileFuture<T>> getChainedFutures() {
        return futures;
    }
}
TOP

Related Classes of com.level3.meanwhile.concurrent.MeanwhileRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.