Futures.addCallback(programPromise, new FutureCallback<CpsThreadGroup>() { final Exception source = new Exception(); // call stack of this object captures who called this. useful during debugging. @Override
/** * Schedules the execution of this thread from the last {@linkplain Continuable#suspend(Object)} point. * * @return * Future that promises the completion of the next {@link #runNextChunk()}. */ public Future<Object> resume(Outcome v) { if (resumeValue != null) { return Futures.immediateFailedFuture(new IllegalStateException("Already resumed with " + resumeValue)); } resumeValue = v; promise = SettableFuture.create(); group.scheduleRun(); return promise; }
@Override public ListenableFuture<List<StepExecution>> getCurrentExecutions(final boolean innerMostOnly) { if (programPromise == null || isComplete()) { return Futures.immediateFuture(Collections.<StepExecution>emptyList());
Futures.addCallback(programPromise, new FutureCallback<CpsThreadGroup>() { @Override public void onSuccess(CpsThreadGroup g) { if (v) {
@Override public ListenableFuture<Void> saveState() { try { final SettableFuture<Void> f = SettableFuture.create(); CpsFlowExecution exec = getFlowExecution(); if (!exec.getDurabilityHint().isPersistWithEveryStep()) { f.set(null); return f; } exec.runInCpsVmThread(new FutureCallback<CpsThreadGroup>() { @Override public void onSuccess(CpsThreadGroup result) { try { // TODO keep track of whether the program was saved anyway after saveState was called but before now, and do not bother resaving it in that case if (result.getExecution().getDurabilityHint().isPersistWithEveryStep()) { result.getExecution().getStorage().flush(); result.saveProgram(); } f.set(null); } catch (Exception x) { f.setException(x); } } @Override public void onFailure(Throwable t) { f.setException(t); } }); return f; } catch (IOException x) { return Futures.immediateFailedFuture(x); } }
Futures.addCallback( r.restorePickles(pickleFutures = new ArrayList<>()),
programPromise = Futures.immediateFailedFuture(ex); throw new IOException("Failed to even create placeholder nodes for execution", ex); } finally { if (programPromise == null) { programPromise = Futures.immediateFailedFuture(new IllegalStateException("completed or broken execution"));
owner.getListener().getLogger().println("Failing build: shutting down master and build is marked to not resume"); final Throwable x = new FlowInterruptedException(Result.ABORTED); Futures.addCallback(this.getCurrentExecutions(/* cf. JENKINS-26148 */true), new FutureCallback<List<StepExecution>>() { @Override public void onSuccess(List<StepExecution> l) { for (StepExecution e : Iterators.reverse(l)) {
programPromise = Futures.immediateFailedFuture(new IllegalStateException("Failed loading heads", failureReason)); LOGGER.log(Level.INFO, "Creating placeholder flownodes for execution: " + this); if (this.owner != null) {
/** Sends {@link StepContext#onFailure} to all running (leaf) steps. */ @RequirePOST public void doTerm() { checkPermission(Item.CANCEL); if (!isInProgress() || /* redundant, but make FindBugs happy */ execution == null) { return; } final Throwable x = new FlowInterruptedException(Result.ABORTED); Futures.addCallback(execution.getCurrentExecutions(/* cf. JENKINS-26148 */true), new FutureCallback<List<StepExecution>>() { @Override public void onSuccess(List<StepExecution> l) { for (StepExecution e : Iterators.reverse(l)) { StepContext context = e.getContext(); context.onFailure(x); try { FlowNode n = context.get(FlowNode.class); if (n != null) { listener.getLogger().println("Terminating " + n.getDisplayFunctionName()); } } catch (Exception x) { LOGGER.log(Level.FINE, null, x); } } } @Override public void onFailure(Throwable t) {} }); printLater(StopState.KILL, "Click here to forcibly kill entire build"); }