-
Notifications
You must be signed in to change notification settings - Fork 104
DRAIN_EXCLUSIVE_ACTIONS
implementation
#1269
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
6384fa7
to
7d3a6fe
Compare
d67e58c
to
43bdda4
Compare
63af06d
to
ee71c0b
Compare
workflow-testing/src/test/java/com/squareup/workflow1/WorkflowsLifecycleTests.kt
Outdated
Show resolved
Hide resolved
ee71c0b
to
f4a3d4e
Compare
DRAIN_EXCLUSIVE_ACTIONS
implementation
f4a3d4e
to
a7dda2e
Compare
// We start by yielding, because if we are on an Unconfined dispatcher, we want to give | ||
// other signals (like Workers listening to the same result) a chance to get dispatched | ||
// and queue their actions. | ||
yield() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Passes the sniff test: This is a "tight" loop that doesn't necessarily suspend (I think sendOutput
is the only suspending call?), so yielding in the middle seems reasonable even if we weren't using an unconfined dispatcher.
@@ -186,11 +187,42 @@ public fun <PropsT, OutputT, RenderingT> renderWorkflowIn( | |||
// we don't surprise anyone with an unexpected rendering pass. Show's over, go home. | |||
if (!isActive) return@launch | |||
|
|||
var drainingActionResult = actionResult | |||
if (runtimeConfig.contains(DRAIN_EXCLUSIVE_ACTIONS)) { | |||
drain@ while (isActive && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we still need this isActive
check since yield
should throw if the job is cancelled?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, its technically not needed. I like it for explicitness sake /readability though. is there an impact of this that i'm not considering and we should remove it?
// Next Render Pass. | ||
var nextRenderAndSnapshot: RenderingAndSnapshot<RenderingT> = runner.nextRendering() | ||
|
||
if (runtimeConfig.contains(CONFLATE_STALE_RENDERINGS)) { | ||
conflate@ while (isActive && actionResult is ActionApplied<*> && actionResult.output == null) { | ||
conflate@ while (isActive && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question about isActive
.
@@ -96,7 +96,12 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>( | |||
private val eventActionsChannel = | |||
Channel<WorkflowAction<PropsT, StateT, OutputT>>(capacity = UNLIMITED) | |||
private var state: StateT | |||
private var subtreeStateDidChange: Boolean = true | |||
|
|||
// Our state or that of one of our descendants changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kdoc
// Our state or that of one of our descendants changed. | ||
private var subtreeStateDirty: Boolean = true | ||
|
||
// Our state changed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kdoc
with(selector) { | ||
eventActionsChannel.onReceive { action -> | ||
return@onReceive applyAction(action) | ||
if (!skipChangedNodes || !selfStateDirty) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Can either of these properties change between line 221 and here? If not, consider assignin to a local val to make it more clear that both these ifs use the same condition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no they can't. and sure I can do that!
private var subtreeStateDirty: Boolean = true | ||
|
||
// Our state changed. | ||
private var selfStateDirty: Boolean = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe i missed it in the code, but it looks like we never set this on its own (without also setting subtreeStateDirty
)? Do we really need it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, lines 349-350 we set them using different conditions when the action is being applied.
// Our state changed.
selfStateDirty = actionApplied.stateChanged
// Our state changed or one of our children's state changed.
subtreeStateDirty = aggregateActionApplied.stateChanged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that's key for drain exclusive because subtreeStateDirty
is true always on a path all the way to the root no matter what changed in the tree. We use selfStateDirty
to determine whether the node is exclusive to the previous action applied because otherwise there would never be any other exclusive nodes that we can process actions on.
dbd02dc
to
934826b
Compare
a7dda2e
to
a877247
Compare
532d1d2
to
abd8f88
Compare
|
abd8f88
to
6e2a691
Compare
6e2a691
to
d6aa364
Compare
d6aa364
to
11ffd77
Compare
If there are multiple actions that are prepared to be applied that are in separate (exclusive) areas of the tree, then apply them all before rendering again.
Also ensure that we track if any of the chained actions have changed state. If they have, then pass the new rendering to the UI!
Update tests to test this behavior.