Skip to content

Add Interceptor Methods for Skip and Update Rendering #1297

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

Merged
merged 1 commit into from
May 7, 2025

Conversation

steve-the-edwards
Copy link
Contributor

@steve-the-edwards steve-the-edwards commented Apr 23, 2025

This is necessary in order to do effective tracing with optimizations enabled.

These are also helpful and quite logical methods for the interceptor, though they are driven from the runtime rather than the workflow definition (so eventually could be extracted to their own type of interceptor interface)

@steve-the-edwards steve-the-edwards force-pushed the sedwards/extend-interceptor branch from 9f2152b to 8f6d19e Compare April 25, 2025 17:15
* as well as two extra parameters:
* This interface's methods mirror the methods of [StatefulWorkflow], and three additional methods,
* explained below.
* Each method returns the same thing as the corresponding method on [StatefulWorkflow], and\
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

\ ?

@@ -129,6 +142,21 @@ public interface WorkflowInterceptor {
session: WorkflowSession
): Snapshot? = proceed(state)

/**
* Called when a [RenderingAndSnapshot] is updated from the runtime (i.e. when the [StateFlow]
* is provided a new value - this may still be de-duplicated).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"this may still be de-duplicated" => by consumers of the state flow, based on some other things?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by the StateFlow itself which de-duplicates emissions downstream.

/**
* Called when the rendering is skipped because no state has changed after action cascade(s).
*/
public fun onRenderingSkipped(): Unit = Unit
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the outcome of an action loop is always either "onRenderingSkipped" or "onRenderingUpdated", then I would actually merge those and pass in a sealed class of "Updated" vs "Skipped", which would make this behavior a lot clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ya I think that sounds reasonable!

*
* @return [RenderingAndSnapshot]: a possibly modified [RenderingAndSnapshot].
*/
public fun <R> onRenderingUpdated(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear from the name that this only applies to the rendering published out to the external consumer. Combined with Py's suggestion below, could we name it something like "onExternalRenderingEvent" (with an updated/skipped parameter).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes I can rename this.

Comment on lines 37 to 42
* 1. [onRenderingSkipped] - called when the rendering is short-circuited because no state
* change was detected as part of the action cascade(s) and the
* [RuntimeConfig.RENDER_ONLY_WHEN_STATE_CHANGES] is enabled.
* 1. [onRenderingUpdated] - called when a [RenderingAndSnapshot] is passed to the [StateFlow]
* returned by [renderWorkflowIn]. It is passed the [RenderingAndSnapshot] which could be
* decorated.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit awkward to me. Up to this point, everything in WorkflowInterceptor is 1-1 with every individual workflow in the system. These new methods, IIUC, apply to the runtime as a whole. I feel like it violates SRP? I don't want to be overly pedantic about it and I don't have any real practical reason to not put them here.

I do wonder if this would be a good excuse to figure out a dedicated, higher-level tracing API though like we'd need for compose-based workflows. I can jump on that this week a bit probably, although I'll be leaving on Friday for 2 weeks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onSessionStarted actually existed before these changes (I just moved the documentation and made it clear).

Yes, agreed that we are violating SRP and there is an opening here for a higher/orthogonal tracing dedicated API. I also don't want to tackle that with this work if possible and the interceptor can handle this without growing any more unwieldy than it already is, I think.

@steve-the-edwards steve-the-edwards force-pushed the sedwards/extend-interceptor branch from 8f6d19e to 248cc99 Compare May 6, 2025 20:27
@steve-the-edwards steve-the-edwards requested a review from a team as a code owner May 6, 2025 20:27
@steve-the-edwards steve-the-edwards changed the base branch from sedwards/drain-exclusive-actions to main May 6, 2025 20:32
public data object RenderPassSkipped : RuntimeLoopOutcome
public data class RenderPassesComplete<R>(
val renderingAndSnapshot: RenderingAndSnapshot<R>
) : RuntimeLoopOutcome
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've avoided data class and data object in public types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching that. Will fix.

Comment on lines 37 to 42
* 1. [onRenderingSkipped] - called when the rendering is short-circuited because no state
* change was detected as part of the action cascade(s) and the
* [RuntimeConfig.RENDER_ONLY_WHEN_STATE_CHANGES] is enabled.
* 1. [onRenderingUpdated] - called when a [RenderingAndSnapshot] is passed to the [StateFlow]
* returned by [renderWorkflowIn]. It is passed the [RenderingAndSnapshot] which could be
* decorated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale kdoc, there is only one new method now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update.

Comment on lines 146 to 147
* Called when a the runtime loop has "iterated." Typically this the application of 1 action
* and 1 render pass.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Called when a the runtime loop has "iterated." Typically this the application of 1 action
* and 1 render pass.
* Called to report the [outcome] of each tick of the runtime loop. In the simplest case
* this is the application of one action and one render pass, but optimizations can
* change that:

Comment on lines 149 to 154
* If there is no state change with the `RENDER_ONLY_WHEN_STATE_CHANGES` optimization,
* it might not be a render pass at all, in which case [RenderPassSkipped] is the outcome.
* In the case of the `CONFLATE_STALE_RENDERINGS` optimization it could be multiple render
* passes.
* If there is at least one render pass, then [RenderPassesComplete] is passed as the outcome,
* which includes the actual [RenderingAndSnapshot] returned from the runtime.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe make this a bullet list.

@steve-the-edwards steve-the-edwards force-pushed the sedwards/extend-interceptor branch from 248cc99 to 6286ac8 Compare May 7, 2025 14:03
@steve-the-edwards steve-the-edwards merged commit 9c8f14c into main May 7, 2025
43 checks passed
@steve-the-edwards steve-the-edwards deleted the sedwards/extend-interceptor branch May 7, 2025 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants