@@ -14,7 +14,6 @@ import com.squareup.workflow1.Workflow
1414import com.squareup.workflow1.WorkflowAction
1515import com.squareup.workflow1.WorkflowExperimentalApi
1616import com.squareup.workflow1.WorkflowExperimentalRuntime
17- import com.squareup.workflow1.WorkflowIdentifier
1817import com.squareup.workflow1.WorkflowInterceptor
1918import com.squareup.workflow1.WorkflowInterceptor.WorkflowSession
2019import com.squareup.workflow1.WorkflowTracer
@@ -50,32 +49,32 @@ import kotlin.reflect.KType
5049 * structured concurrency).
5150 */
5251@OptIn(WorkflowExperimentalApi ::class , WorkflowExperimentalRuntime ::class )
53- internal class WorkflowNode <PropsT , StateT , OutputT , RenderingT >(
54- val id : WorkflowNodeId ,
52+ internal class StatefulWorkflowNode <PropsT , StateT , OutputT , RenderingT >(
53+ id : WorkflowNodeId ,
5554 workflow : StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >,
5655 initialProps : PropsT ,
5756 snapshot : TreeSnapshot ? ,
5857 baseContext : CoroutineContext ,
5958 // Providing default value so we don't need to specify in test.
60- override val runtimeConfig : RuntimeConfig = RuntimeConfigOptions .DEFAULT_CONFIG ,
61- override val workflowTracer : WorkflowTracer ? = null ,
62- private val emitAppliedActionToParent : (ActionApplied <OutputT >) -> ActionProcessingResult =
63- { it },
64- override val parent : WorkflowSession ? = null ,
65- private val interceptor : WorkflowInterceptor = NoopWorkflowInterceptor ,
59+ runtimeConfig : RuntimeConfig = RuntimeConfigOptions .DEFAULT_CONFIG ,
60+ workflowTracer : WorkflowTracer ? = null ,
61+ emitAppliedActionToParent : (ActionApplied <OutputT >) -> ActionProcessingResult = { it },
62+ parent : WorkflowSession ? = null ,
63+ interceptor : WorkflowInterceptor = NoopWorkflowInterceptor ,
6664 idCounter : IdCounter ? = null
67- ) : CoroutineScope, SideEffectRunner, RememberStore, WorkflowSession {
65+ ) : AbstractWorkflowNode<PropsT, OutputT, RenderingT>(
66+ id = id,
67+ runtimeConfig = runtimeConfig,
68+ workflowTracer = workflowTracer,
69+ parent = parent,
70+ baseContext = baseContext,
71+ idCounter = idCounter,
72+ interceptor = interceptor,
73+ emitAppliedActionToParent = emitAppliedActionToParent,
74+ ),
75+ SideEffectRunner ,
76+ RememberStore {
6877
69- /* *
70- * Context that has a job that will live as long as this node.
71- * Also adds a debug name to this coroutine based on its ID.
72- */
73- override val coroutineContext = baseContext + Job (baseContext[Job ]) + CoroutineName (id.toString())
74-
75- // WorkflowInstance properties
76- override val identifier: WorkflowIdentifier get() = id.identifier
77- override val renderKey: String get() = id.name
78- override val sessionId: Long = idCounter.createId()
7978 private var cachedWorkflowInstance: StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >
8079 private var interceptedWorkflowInstance: StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >
8180
@@ -116,45 +115,37 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
116115 state = interceptedWorkflowInstance.initialState(initialProps, snapshot?.workflowSnapshot, this )
117116 }
118117
119- override fun toString (): String {
120- val parentDescription = parent?.let { " WorkflowInstance(…)" }
121- return " WorkflowInstance(" +
122- " identifier=$identifier , " +
123- " renderKey=$renderKey , " +
124- " instanceId=$sessionId , " +
125- " parent=$parentDescription " +
126- " )"
127- }
128-
129118 /* *
130119 * Walk the tree of workflows, rendering each one and using
131120 * [RenderContext][com.squareup.workflow1.BaseRenderContext] to give its children a chance to
132121 * render themselves and aggregate those child renderings.
133122 */
134123 @Suppress(" UNCHECKED_CAST" )
135- fun render (
136- workflow : StatefulWorkflow <PropsT , * , OutputT , RenderingT >,
124+ override fun render (
125+ workflow : Workflow <PropsT , OutputT , RenderingT >,
137126 input : PropsT
138- ): RenderingT =
139- renderWithStateType(workflow as StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >, input)
127+ ): RenderingT = renderWithStateType(
128+ workflow = workflow.asStatefulWorkflow() as StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >,
129+ props = input
130+ )
140131
141132 /* *
142133 * Walk the tree of state machines again, this time gathering snapshots and aggregating them
143134 * automatically.
144135 */
145- fun snapshot (workflow : StatefulWorkflow < * , * , * , * > ): TreeSnapshot {
146- @Suppress( " UNCHECKED_CAST " )
147- val typedWorkflow = workflow as StatefulWorkflow < PropsT , StateT , OutputT , RenderingT >
148- maybeUpdateCachedWorkflowInstance(typedWorkflow )
149- return interceptor.onSnapshotStateWithChildren({
150- val childSnapshots = subtreeManager.createChildSnapshots()
151- val rootSnapshot = interceptedWorkflowInstance.snapshotState(state)
152- TreeSnapshot (
153- workflowSnapshot = rootSnapshot,
154- // Create the snapshots eagerly since subtreeManager is mutable.
155- childTreeSnapshots = { childSnapshots }
156- )
157- }, this )
136+ override fun snapshot (): TreeSnapshot {
137+ return interceptor.onSnapshotStateWithChildren(
138+ proceed = {
139+ val childSnapshots = subtreeManager.createChildSnapshots( )
140+ val rootSnapshot = interceptedWorkflowInstance.snapshotState(state)
141+ TreeSnapshot (
142+ workflowSnapshot = rootSnapshot,
143+ // Create the snapshots eagerly since subtreeManager is mutable.
144+ childTreeSnapshots = { childSnapshots }
145+ )
146+ },
147+ session = this
148+ )
158149 }
159150
160151 override fun runningSideEffect (
@@ -212,7 +203,7 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
212203 * time of suspending.
213204 */
214205 @OptIn(ExperimentalCoroutinesApi ::class , DelicateCoroutinesApi ::class )
215- fun onNextAction (selector : SelectBuilder <ActionProcessingResult >): Boolean {
206+ override fun onNextAction (selector : SelectBuilder <ActionProcessingResult >): Boolean {
216207 // Listen for any child workflow updates.
217208 var empty = subtreeManager.onNextChildAction(selector)
218209
@@ -230,11 +221,11 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
230221 /* *
231222 * Cancels this state machine host, and any coroutines started as children of it.
232223 *
233- * This must be called when the caller will no longer call [onNextAction]. It is an error to call [onNextAction]
234- * after calling this method.
224+ * This must be called when the caller will no longer call [onNextAction]. It is an error to call
225+ * [onNextAction] after calling this method.
235226 */
236- fun cancel (cause : CancellationException ? = null ) {
237- coroutineContext .cancel(cause)
227+ override fun cancel (cause : CancellationException ? ) {
228+ super .cancel(cause)
238229 lastRendering = NullableInitBox ()
239230 }
240231
@@ -314,7 +305,6 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
314305 * Applies [action] to this workflow's [state] and then passes the resulting [ActionApplied]
315306 * via [emitAppliedActionToParent] to the parent, with additional information as to whether or
316307 * not this action has changed the current node's state.
317- *
318308 */
319309 private fun applyAction (
320310 action : WorkflowAction <PropsT , StateT , OutputT >,
0 commit comments