Class CpsFlowExecution
java.lang.Object
org.jenkinsci.plugins.workflow.flow.FlowExecution
org.jenkinsci.plugins.workflow.cps.CpsFlowExecution
- All Implemented Interfaces:
org.jenkinsci.plugins.workflow.flow.BlockableResume,org.jenkinsci.plugins.workflow.graph.FlowActionStorage,org.jenkinsci.plugins.workflow.graph.GraphLookupView
public class CpsFlowExecution
extends org.jenkinsci.plugins.workflow.flow.FlowExecution
implements org.jenkinsci.plugins.workflow.flow.BlockableResume
FlowExecution implemented with Groovy CPS.
State Transition
CpsFlowExecution goes through the following states:
+----------------------+
| |
v |
PERSISTED --> PREPARING --> SUSPENDED --> RUNNABLE --> RUNNING --> COMPLETE
^
|
INITIAL
- INITIAL
-
When a new
CpsFlowExecutionis created, it starts from here. Whenstart()method is called, we get one thread scheduled, and we arrive at RUNNABLE state. - PERSISTED
-
CpsFlowExecutionis on disk with its owner, for example inbuild.xmlof the workflow run. Nothing exists in memory. For example, Jenkins is not running. Transition from this into PREPARING is triggered outside our control by XStream usingCpsFlowExecution.ConverterImplto unmarshalCpsFlowExecution.FlowExecution.onLoad()is called at the end, and we arrive at the PREPARING state. - PREPARING
-
CpsFlowExecutionis in memory, butCpsThreadGroupisn't. We are trying to restore all the ephemeral pickles that are necessary to get workflow going again.programPromiserepresents a promise of completing this state.PickleResolverkeeps track of this, and when it's all done, we arrive at SUSPENDED state. - SUSPENDED
-
CpsThreadGroupis in memory, but allCpsThreads are not runnable, which means they are waiting for some conditions to trigger (such as a completion of a shell script that's executing, human approval, etc).CpsFlowExecutionandCpsThreadGroupare safe to persist. When a condition is met,CpsThread.resume(Outcome)is called, and that thread becomes runnable, and we move to the RUNNABLE state. - RUNNABLE
-
Some of
CpsThreads are runnable, but we aren't actually running. The conditions that triggeredCpsThreadis captured inCpsThread.resumeValue. As we get into this state,CpsThreadGroup.scheduleRun()should be called to schedule the execution.CpsFlowExecutionandCpsThreadGroupare safe to persist in this state, just like in the SUSPENDED state. WhenCpsThreadGroup.runnerallocated a real Java thread to the execution, we move to the RUNNING state. - RUNNING
-
A thread is inside
CpsThreadGroup.run()and is actively mutating the object graph inside the script. This state continues until no threads are runnable any more. Only one thread executesCpsThreadGroup.run(). In this state,CpsFlowExecutionstill need to be persistable (because generally we don't get to control when it is persisted), butCpsThreadGroupisn't safe to persist. When the Java thread leavesCpsThreadGroup.run(), we move to the SUSPENDED state. - COMPLETE
-
All the
CpsThreads have terminated and there's nothing more to execute, and there's no more events to wait. The result is finalized and there's no further state change.
- Author:
- Kohsuke Kawaguchi
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classstatic classstatic classNested classes/interfaces inherited from interface org.jenkinsci.plugins.workflow.graph.GraphLookupView
org.jenkinsci.plugins.workflow.graph.GraphLookupView.EnclosingBlocksIterable -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic booleanIftrue, then when the execution completes, we migrate the flow node storage fromSimpleXStreamFlowNodeStoragetoBulkFlowNodeStorage.com.google.common.util.concurrent.ListenableFuture<CpsThreadGroup>Loading of the program is asynchronous because it requires us to re-obtain stateful objects.Fields inherited from class org.jenkinsci.plugins.workflow.flow.FlowExecution
durabilityHint, internalGraphLookup -
Constructor Summary
ConstructorsConstructorDescriptionCpsFlowExecution(String script, boolean sandbox, org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner) CpsFlowExecution(String script, boolean sandbox, org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner, org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint durabilityHint) CpsFlowExecution(String script, org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner) Deprecated. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddListener(org.jenkinsci.plugins.workflow.flow.GraphListener listener) protected voidbooleanSee JENKINS-22941 for why this exists.booleanIf true, we are allowed to resume the build because resume is enabled AND we shut down cleanly.org.springframework.security.core.Authenticationcom.google.common.util.concurrent.ListenableFuture<List<org.jenkinsci.plugins.workflow.steps.StepExecution>>getCurrentExecutions(boolean innerMostOnly) List<org.jenkinsci.plugins.workflow.graph.FlowNode>org.jenkinsci.plugins.workflow.cps.FlowHeadgetFlowHead(int id) getNextScriptName(String path) Finds the expected next loaded script name, likeScript1.org.jenkinsci.plugins.workflow.graph.FlowNodeorg.jenkinsci.plugins.workflow.flow.FlowExecutionOwnergetOwner()groovy.lang.GroovyShellgetShell()Returns a groovy compiler used to load the script.org.jenkinsci.plugins.workflow.support.storage.FlowNodeStorageDirectory where workflow stores its state.Synchronously obtain the current state of the workflow program.groovy.lang.GroovyShellReturns a groovy compiler used to load the trusted script.protected voidvoidinterrupt(Result result, CauseOfInterruption... causes) intiota()iotaStr()Assigns a new ID.booleanbooleanisCurrentHead(org.jenkinsci.plugins.workflow.graph.FlowNode n) booleanHas the execution been marked done - note that legacy builds may not have that flag persisted, in which case we look for a single FlowEndNode head (see:isComplete()andFlowExecution.isComplete())booleanisPaused()booleanIf true, pipeline is forbidden to resume even if it can.booleanTrue if executing with groovy-sandbox, false if executing with approval.loadActions(org.jenkinsci.plugins.workflow.graph.FlowNode node) voidloadProgramAsync(File programDataFile) DeserializesCpsThreadGroupfromgetProgramDataFile()if necessary.static voidmaybeAutoPersistNode(org.jenkinsci.plugins.workflow.graph.FlowNode node) Invoke me to toggle autopersist back on for steps that delay it.voidonLoad(org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner) voidpause(boolean v) Pause or unpause the execution.voidremoveListener(org.jenkinsci.plugins.workflow.flow.GraphListener listener) voidsaveActions(org.jenkinsci.plugins.workflow.graph.FlowNode node, List<Action> actions) voidvoidsetResumeBlocked(boolean resumeBlocked) voidstart()static voidtoString()voidDeprecated.Methods inherited from class org.jenkinsci.plugins.workflow.flow.FlowExecution
findAllEnclosingBlockStarts, findEnclosingBlockStart, getAuthentication, getCauseOfFailure, getCurrentExecutions, getDurabilityHint, getEndNode, getInternalGraphLookup, getUrl, isActive, iterateEnclosingBlocks, onLoad
-
Field Details
-
OPTIMIZE_STORAGE_UPON_COMPLETION
public static boolean OPTIMIZE_STORAGE_UPON_COMPLETIONIftrue, then when the execution completes, we migrate the flow node storage fromSimpleXStreamFlowNodeStoragetoBulkFlowNodeStorage. -
programPromise
public transient volatile com.google.common.util.concurrent.ListenableFuture<CpsThreadGroup> programPromiseLoading of the program is asynchronous because it requires us to re-obtain stateful objects. This object represents aFuturefor filling inCpsThreadGroup. TODO: provide a mechanism to diagnose how far along this process is.- See Also:
-
runInCpsVmThread(FutureCallback)
-
-
Constructor Details
-
CpsFlowExecution
@Deprecated public CpsFlowExecution(String script, org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner) throws IOException Deprecated.- Throws:
IOException
-
CpsFlowExecution
public CpsFlowExecution(@NonNull String script, boolean sandbox, @NonNull org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner, @CheckForNull org.jenkinsci.plugins.workflow.flow.FlowDurabilityHint durabilityHint) throws IOException - Throws:
IOException
-
CpsFlowExecution
public CpsFlowExecution(String script, boolean sandbox, org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner owner) throws IOException - Throws:
IOException
-
-
Method Details
-
isResumeBlocked
public boolean isResumeBlocked()If true, pipeline is forbidden to resume even if it can.- Specified by:
isResumeBlockedin interfaceorg.jenkinsci.plugins.workflow.flow.BlockableResume
-
setResumeBlocked
public void setResumeBlocked(boolean resumeBlocked) - Specified by:
setResumeBlockedin interfaceorg.jenkinsci.plugins.workflow.flow.BlockableResume
-
getShell
public groovy.lang.GroovyShell getShell()Returns a groovy compiler used to load the script.- See Also:
-
- "doc/classloader.md"
GroovyShell.getClassLoader()
-
getTrustedShell
public groovy.lang.GroovyShell getTrustedShell()Returns a groovy compiler used to load the trusted script.- See Also:
-
- "doc/classloader.md"
-
getStorage
public org.jenkinsci.plugins.workflow.support.storage.FlowNodeStorage getStorage() -
getScript
-
getLoadedScripts
-
isSandbox
public boolean isSandbox()True if executing with groovy-sandbox, false if executing with approval. -
getOwner
public org.jenkinsci.plugins.workflow.flow.FlowExecutionOwner getOwner()- Specified by:
getOwnerin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
getStorageDir
Directory where workflow stores its state.- Throws:
IOException
-
start
- Specified by:
startin classorg.jenkinsci.plugins.workflow.flow.FlowExecution- Throws:
IOException
-
iotaStr
Assigns a new ID. -
iota
@Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) public int iota() -
initializeStorage
- Throws:
IOException
-
canResume
public boolean canResume()If true, we are allowed to resume the build because resume is enabled AND we shut down cleanly. -
onLoad
- Overrides:
onLoadin classorg.jenkinsci.plugins.workflow.flow.FlowExecution- Throws:
IOException
-
loadProgramAsync
DeserializesCpsThreadGroupfromgetProgramDataFile()if necessary. This moves us into the PREPARING state.- Parameters:
programDataFile-
-
afterStepExecutionsResumed
protected void afterStepExecutionsResumed()- Overrides:
afterStepExecutionsResumedin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
blocksRestart
public boolean blocksRestart()See JENKINS-22941 for why this exists.- Overrides:
blocksRestartin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
waitForSuspension
Deprecated.Use some other idiom, likeSemaphoreStep.Waits for the workflow to move into the SUSPENDED state. -
getFlowHead
@CheckForNull public org.jenkinsci.plugins.workflow.cps.FlowHead getFlowHead(int id) -
getCurrentHeads
- Specified by:
getCurrentHeadsin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
getCurrentExecutions
public com.google.common.util.concurrent.ListenableFuture<List<org.jenkinsci.plugins.workflow.steps.StepExecution>> getCurrentExecutions(boolean innerMostOnly) - Overrides:
getCurrentExecutionsin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
getThreadDump
Synchronously obtain the current state of the workflow program.The workflow can be already completed, or it can still be running.
-
isCurrentHead
public boolean isCurrentHead(org.jenkinsci.plugins.workflow.graph.FlowNode n) - Specified by:
isCurrentHeadin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
addListener
public void addListener(org.jenkinsci.plugins.workflow.flow.GraphListener listener) - Specified by:
addListenerin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
removeListener
public void removeListener(org.jenkinsci.plugins.workflow.flow.GraphListener listener) - Overrides:
removeListenerin classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
interrupt
public void interrupt(Result result, CauseOfInterruption... causes) throws IOException, InterruptedException - Specified by:
interruptin classorg.jenkinsci.plugins.workflow.flow.FlowExecution- Throws:
IOExceptionInterruptedException
-
getNode
- Specified by:
getNodein classorg.jenkinsci.plugins.workflow.flow.FlowExecution- Throws:
IOException
-
setResult
-
getResult
-
loadActions
public List<Action> loadActions(org.jenkinsci.plugins.workflow.graph.FlowNode node) throws IOException - Specified by:
loadActionsin interfaceorg.jenkinsci.plugins.workflow.graph.FlowActionStorage- Throws:
IOException
-
saveActions
public void saveActions(org.jenkinsci.plugins.workflow.graph.FlowNode node, List<Action> actions) throws IOException - Specified by:
saveActionsin interfaceorg.jenkinsci.plugins.workflow.graph.FlowActionStorage- Throws:
IOException
-
maybeAutoPersistNode
public static void maybeAutoPersistNode(@NonNull org.jenkinsci.plugins.workflow.graph.FlowNode node) Invoke me to toggle autopersist back on for steps that delay it. -
isComplete
public boolean isComplete()- Overrides:
isCompletein classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
getAuthentication2
public org.springframework.security.core.Authentication getAuthentication2()- Overrides:
getAuthentication2in classorg.jenkinsci.plugins.workflow.flow.FlowExecution
-
getNextScriptName
@Restricted(org.kohsuke.accmod.restrictions.NoExternalUse.class) public String getNextScriptName(String path) Finds the expected next loaded script name, likeScript1.- Parameters:
path- a file path being loaded (currently ignored)
-
isDoneFlagSet
public boolean isDoneFlagSet()Has the execution been marked done - note that legacy builds may not have that flag persisted, in which case we look for a single FlowEndNode head (see:isComplete()andFlowExecution.isComplete()) -
isPaused
public boolean isPaused() -
pause
Pause or unpause the execution.- Parameters:
v- true to pause, false to unpause.- Throws:
IOException
-
toString
-
suspendAll
@Restricted(org.kohsuke.accmod.restrictions.DoNotUse.class) @Terminator(attains="FlowExecutionList.EXECUTIONS_SUSPENDED") public static void suspendAll()
-
SemaphoreStep.