@@ -14,7 +14,6 @@ import com.squareup.workflow1.Workflow
14
14
import com.squareup.workflow1.WorkflowAction
15
15
import com.squareup.workflow1.WorkflowExperimentalApi
16
16
import com.squareup.workflow1.WorkflowExperimentalRuntime
17
- import com.squareup.workflow1.WorkflowIdentifier
18
17
import com.squareup.workflow1.WorkflowInterceptor
19
18
import com.squareup.workflow1.WorkflowInterceptor.WorkflowSession
20
19
import com.squareup.workflow1.WorkflowTracer
@@ -50,32 +49,32 @@ import kotlin.reflect.KType
50
49
* structured concurrency).
51
50
*/
52
51
@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 ,
55
54
workflow : StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >,
56
55
initialProps : PropsT ,
57
56
snapshot : TreeSnapshot ? ,
58
57
baseContext : CoroutineContext ,
59
58
// 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 ,
66
64
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 {
68
77
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()
79
78
private var cachedWorkflowInstance: StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >
80
79
private var interceptedWorkflowInstance: StatefulWorkflow <PropsT , StateT , OutputT , RenderingT >
81
80
@@ -116,45 +115,37 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
116
115
state = interceptedWorkflowInstance.initialState(initialProps, snapshot?.workflowSnapshot, this )
117
116
}
118
117
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
-
129
118
/* *
130
119
* Walk the tree of workflows, rendering each one and using
131
120
* [RenderContext][com.squareup.workflow1.BaseRenderContext] to give its children a chance to
132
121
* render themselves and aggregate those child renderings.
133
122
*/
134
123
@Suppress(" UNCHECKED_CAST" )
135
- fun render (
136
- workflow : StatefulWorkflow <PropsT , * , OutputT , RenderingT >,
124
+ override fun render (
125
+ workflow : Workflow <PropsT , OutputT , RenderingT >,
137
126
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
+ )
140
131
141
132
/* *
142
133
* Walk the tree of state machines again, this time gathering snapshots and aggregating them
143
134
* automatically.
144
135
*/
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
+ )
158
149
}
159
150
160
151
override fun runningSideEffect (
@@ -212,7 +203,7 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
212
203
* time of suspending.
213
204
*/
214
205
@OptIn(ExperimentalCoroutinesApi ::class , DelicateCoroutinesApi ::class )
215
- fun onNextAction (selector : SelectBuilder <ActionProcessingResult >): Boolean {
206
+ override fun onNextAction (selector : SelectBuilder <ActionProcessingResult >): Boolean {
216
207
// Listen for any child workflow updates.
217
208
var empty = subtreeManager.onNextChildAction(selector)
218
209
@@ -230,11 +221,11 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
230
221
/* *
231
222
* Cancels this state machine host, and any coroutines started as children of it.
232
223
*
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.
235
226
*/
236
- fun cancel (cause : CancellationException ? = null ) {
237
- coroutineContext .cancel(cause)
227
+ override fun cancel (cause : CancellationException ? ) {
228
+ super .cancel(cause)
238
229
lastRendering = NullableInitBox ()
239
230
}
240
231
@@ -314,7 +305,6 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
314
305
* Applies [action] to this workflow's [state] and then passes the resulting [ActionApplied]
315
306
* via [emitAppliedActionToParent] to the parent, with additional information as to whether or
316
307
* not this action has changed the current node's state.
317
- *
318
308
*/
319
309
private fun applyAction (
320
310
action : WorkflowAction <PropsT , StateT , OutputT >,
0 commit comments