Search in sources :

Example 1 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsFlowExecution method start.

@Override
public void start() throws IOException {
    final CpsScript s = parseScript();
    scriptClass = s.getClass();
    s.$initialize();
    final FlowHead h = new FlowHead(this);
    synchronized (this) {
        heads.put(h.getId(), h);
    }
    h.newStartNode(new FlowStartNode(this, iotaStr()));
    final CpsThreadGroup g = new CpsThreadGroup(this);
    g.register(s);
    final SettableFuture<CpsThreadGroup> f = SettableFuture.create();
    programPromise = f;
    // Ensures we've saves the WorkFlowRun at least once with initial state
    saveOwner();
    g.runner.submit(new Runnable() {

        @Override
        public void run() {
            CpsThread t = g.addThread(new Continuable(s, createInitialEnv()), h, null);
            t.resume(new Outcome(null, null));
            f.set(g);
        }

        /**
         * Environment to start executing the script in.
         * During sandbox execution, we need to call sandbox interceptor while executing asynchronous code.
         */
        private Env createInitialEnv() {
            return Envs.empty(isSandbox() ? new SandboxInvoker() : new DefaultInvoker());
        }
    });
}
Also used : FlowStartNode(org.jenkinsci.plugins.workflow.graph.FlowStartNode) DefaultInvoker(com.cloudbees.groovy.cps.sandbox.DefaultInvoker) Env(com.cloudbees.groovy.cps.Env) SandboxInvoker(com.cloudbees.groovy.cps.sandbox.SandboxInvoker) Outcome(com.cloudbees.groovy.cps.Outcome) Continuable(com.cloudbees.groovy.cps.Continuable)

Example 2 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsThread method runNextChunk.

/**
 * Executes CPS code synchronously a little bit more, until it hits
 * the point the workflow needs to be dehydrated.
 */
@SuppressWarnings("rawtypes")
@Nonnull
Outcome runNextChunk() {
    assert program != null;
    Outcome outcome;
    final CpsThread old = CURRENT.get();
    CURRENT.set(this);
    try (Timeout timeout = Timeout.limit(5, TimeUnit.MINUTES)) {
        LOGGER.log(FINE, "runNextChunk on {0}", resumeValue);
        final Outcome o = resumeValue;
        resumeValue = null;
        outcome = program.run0(o, categories);
        if (outcome.getAbnormal() != null) {
            LOGGER.log(FINE, "ran and produced error", outcome.getAbnormal());
        } else {
            LOGGER.log(FINE, "ran and produced {0}", outcome);
        }
        if (outcome.getNormal() instanceof ThreadTask) {
            // if an execution in the thread safepoint is requested, deliver that
            ThreadTask sc = (ThreadTask) outcome.getNormal();
            ThreadTaskResult r = sc.eval(this);
            if (r.resume != null) {
                // yield, then keep evaluating the CPS code
                resumeValue = r.resume;
            } else {
                // break but with a different value
                outcome = r.suspend;
            }
        }
    } finally {
        CURRENT.set(old);
    }
    if (promise != null) {
        if (outcome.isSuccess())
            promise.set(outcome.getNormal());
        else {
            try {
                promise.setException(outcome.getAbnormal());
            } catch (Error e) {
                if (e == outcome.getAbnormal()) {
                    // affects other places that use SettableFuture
                    ;
                } else {
                    throw e;
                }
            }
        }
        promise = null;
    }
    return outcome;
}
Also used : Outcome(com.cloudbees.groovy.cps.Outcome) Timeout(org.jenkinsci.plugins.workflow.support.concurrent.Timeout) Nonnull(javax.annotation.Nonnull)

Example 3 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project groovy-cps by cloudbees.

the class GreenThread method start.

/**
 * Creates a new green thread that executes the given closure.
 */
public void start() {
    Block b;
    try {
        run();
        // closure had run synchronously.
        b = Block.NOOP;
    } catch (CpsCallableInvocation inv) {
        // this will create a thread, and resume with the newly created thread
        b = inv.asBlock();
    } catch (Throwable t) {
        // closure had run synchronously and failed
        b = new ThrowBlock(new ConstantBlock(t));
    }
    final Block bb = b;
    invoke(new ThreadTask() {

        public Result eval(GreenWorld w) {
            w = w.withNewThread(new GreenThreadState(GreenThread.this, bb));
            return new Result(w, new Outcome(GreenThread.this, null), false);
        }
    });
    // thus the code will never reach here
    throw new AssertionError();
}
Also used : ThrowBlock(com.cloudbees.groovy.cps.impl.ThrowBlock) ConstantBlock(com.cloudbees.groovy.cps.impl.ConstantBlock) CpsCallableInvocation(com.cloudbees.groovy.cps.impl.CpsCallableInvocation) Outcome(com.cloudbees.groovy.cps.Outcome) Block(com.cloudbees.groovy.cps.Block) ConstantBlock(com.cloudbees.groovy.cps.impl.ConstantBlock) ThrowBlock(com.cloudbees.groovy.cps.impl.ThrowBlock)

Example 4 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project groovy-cps by cloudbees.

the class GreenWorld method update.

/**
 * Called when we execute something in one of the member thread.
 *
 * We'll build an updated {@link GreenWorld} then return it.
 */
Next update(GreenThreadState g) {
    GreenWorld d = this.with(g);
    Outcome y = g.n.yield;
    if (y == null) {
        // no yield. rotate to next thread and keep going
        return d.withNewCur().asNext(null);
    }
    if (y.getNormal() instanceof ThreadTask) {
        // a task that needs to update/access the state
        ThreadTask task = (ThreadTask) y.getNormal();
        Result r = task.eval(d);
        d = r.w;
        if (// yield the value, then come back to the current thread later
        r.suspend)
            return d.asNext(r.value);
        else
            return d.update(g.resumeFrom(r.value));
    } else {
        // other Outcome is for caller
        return d.asNext(y);
    }
}
Also used : Outcome(com.cloudbees.groovy.cps.Outcome)

Example 5 with Outcome

use of com.cloudbees.groovy.cps.Outcome in project workflow-cps-plugin by jenkinsci.

the class CpsFlowExecution method loadProgramFailed.

/**
 * Used by {@link #loadProgramAsync(File)} to propagate a failure to load the persisted execution state.
 * <p>
 * Let the workflow interrupt by throwing an exception that indicates how it failed.
 * @param promise same as {@link #programPromise} but more strongly typed
 */
private void loadProgramFailed(final Throwable problem, SettableFuture<CpsThreadGroup> promise) {
    FlowHead head;
    synchronized (this) {
        if (heads == null || heads.isEmpty()) {
            head = null;
        } else {
            head = getFirstHead();
        }
    }
    if (head == null) {
        // something went catastrophically wrong and there's no live head. fake one
        head = new FlowHead(this);
        try {
            head.newStartNode(new FlowStartNode(this, iotaStr()));
        } catch (IOException e) {
            LOGGER.log(Level.FINE, "Failed to persist", e);
        }
    }
    CpsThreadGroup g = new CpsThreadGroup(this);
    final FlowHead head_ = head;
    promise.set(g);
    runInCpsVmThread(new FutureCallback<CpsThreadGroup>() {

        @Override
        public void onSuccess(CpsThreadGroup g) {
            CpsThread t = g.addThread(new Continuable(new ThrowBlock(new ConstantBlock(problem instanceof AbortException ? problem : new IOException("Failed to load build state", problem)))), head_, null);
            t.resume(new Outcome(null, null));
        }

        @Override
        public void onFailure(Throwable t) {
            LOGGER.log(Level.WARNING, "Failed to set program failure on " + owner, t);
            croak(t);
        }
    });
}
Also used : FlowStartNode(org.jenkinsci.plugins.workflow.graph.FlowStartNode) ThrowBlock(com.cloudbees.groovy.cps.impl.ThrowBlock) IOException(java.io.IOException) ConstantBlock(com.cloudbees.groovy.cps.impl.ConstantBlock) Outcome(com.cloudbees.groovy.cps.Outcome) Continuable(com.cloudbees.groovy.cps.Continuable) AbortException(hudson.AbortException)

Aggregations

Outcome (com.cloudbees.groovy.cps.Outcome)9 Continuable (com.cloudbees.groovy.cps.Continuable)2 ConstantBlock (com.cloudbees.groovy.cps.impl.ConstantBlock)2 CpsCallableInvocation (com.cloudbees.groovy.cps.impl.CpsCallableInvocation)2 ThrowBlock (com.cloudbees.groovy.cps.impl.ThrowBlock)2 IOException (java.io.IOException)2 ErrorAction (org.jenkinsci.plugins.workflow.actions.ErrorAction)2 FlowStartNode (org.jenkinsci.plugins.workflow.graph.FlowStartNode)2 Block (com.cloudbees.groovy.cps.Block)1 Env (com.cloudbees.groovy.cps.Env)1 DefaultInvoker (com.cloudbees.groovy.cps.sandbox.DefaultInvoker)1 SandboxInvoker (com.cloudbees.groovy.cps.sandbox.SandboxInvoker)1 AbortException (hudson.AbortException)1 Action (hudson.model.Action)1 Result (hudson.model.Result)1 Nonnull (javax.annotation.Nonnull)1 BodyInvocationAction (org.jenkinsci.plugins.workflow.actions.BodyInvocationAction)1 StepStartNode (org.jenkinsci.plugins.workflow.cps.nodes.StepStartNode)1 FlowNode (org.jenkinsci.plugins.workflow.graph.FlowNode)1 BodyExecutionCallback (org.jenkinsci.plugins.workflow.steps.BodyExecutionCallback)1