Skip to content

Commit 8f4cebb

Browse files
1338: Clean up caches after WorkflowNode torn down
1 parent 82ca010 commit 8f4cebb

File tree

2 files changed

+22
-5
lines changed

2 files changed

+22
-5
lines changed

workflow-core/src/commonMain/kotlin/com/squareup/workflow1/StatelessWorkflow.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ public abstract class StatelessWorkflow<PropsT, OutputT, out RenderingT> :
227227
* Class type returned by [asStatefulWorkflow].
228228
* See [statefulWorkflow] for the instance.
229229
*/
230-
private inner class StatelessAsStatefulWorkflow :
230+
inner class StatelessAsStatefulWorkflow :
231231
StatefulWorkflow<PropsT, Unit, OutputT, RenderingT>() {
232232

233233
/**
@@ -268,6 +268,23 @@ public abstract class StatelessWorkflow<PropsT, OutputT, out RenderingT> :
268268
}
269269

270270
override fun snapshotState(state: Unit): Snapshot? = null
271+
272+
/**
273+
* When we are finished with at least one node that holds on to this workflow instance,
274+
* then we clear the cache. The reason we do that every time is that it *might* be the last
275+
* node that is caching this instance, and if so, we do not want to leak these cached
276+
* render contexts.
277+
*
278+
* Yes, that means that it might have to be re-created again when this instance is used
279+
* multiple times. The current design for how we get a [StatefulWorkflow] from the
280+
* [StatelessWorkflow] is a failed compromise between performance (caching) and type-safe
281+
* brevity (erasing the `StateT` type from the concerns of [StatelessWorkflow]). It needs
282+
* to be fixed with a bigger re-write (https://github.com/square/workflow-kotlin/issues/1337).
283+
*/
284+
fun clearCache() {
285+
cachedStatelessRenderContext = null
286+
canonicalStatefulRenderContext = null
287+
}
271288
}
272289

273290
private val statefulWorkflow: StatefulWorkflow<PropsT, Unit, OutputT, RenderingT> =

workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/internal/WorkflowNode.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import com.squareup.workflow1.RuntimeConfig
99
import com.squareup.workflow1.RuntimeConfigOptions
1010
import com.squareup.workflow1.RuntimeConfigOptions.PARTIAL_TREE_RENDERING
1111
import com.squareup.workflow1.StatefulWorkflow
12+
import com.squareup.workflow1.StatelessWorkflow
1213
import com.squareup.workflow1.TreeSnapshot
1314
import com.squareup.workflow1.Workflow
1415
import com.squareup.workflow1.WorkflowAction
@@ -234,11 +235,10 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
234235
* after calling this method.
235236
*/
236237
fun cancel(cause: CancellationException? = null) {
237-
// No other cleanup work should be done in this function, since it will only be invoked when
238-
// this workflow is *directly* discarded by its parent (or the host).
239-
// If you need to do something whenever this workflow is torn down, add it to the
240-
// invokeOnCompletion handler for the Job above.
241238
coroutineContext.cancel(cause)
239+
lastRendering = NullableInitBox()
240+
(cachedWorkflowInstance as?
241+
StatelessWorkflow<PropsT, OutputT, RenderingT>.StatelessAsStatefulWorkflow)?.clearCache()
242242
}
243243

244244
/**

0 commit comments

Comments
 (0)