Skip to content

Commit 798e450

Browse files
Add Dispatch Tracking
1 parent b9e854e commit 798e450

File tree

10 files changed

+65
-14
lines changed

10 files changed

+65
-14
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ public interface WorkflowInterceptor {
223223
/** The [RuntimeConfig] of the runtime this session is executing in. */
224224
public val runtimeConfig: RuntimeConfig
225225

226+
/** The [CoroutineContext] of the runtime this session is executing in. */
227+
public val runtimeContext: CoroutineContext
228+
226229
/** The optional [WorkflowTracer] of the runtime this session is executing in. */
227230
public val workflowTracer: WorkflowTracer?
228231
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ internal class WorkflowNode<PropsT, StateT, OutputT, RenderingT>(
7171
*/
7272
override val coroutineContext = baseContext + Job(baseContext[Job]) + CoroutineName(id.toString())
7373

74+
override val runtimeContext: CoroutineContext
75+
get() = coroutineContext
76+
7477
// WorkflowInstance properties
7578
override val identifier: WorkflowIdentifier get() = id.identifier
7679
override val renderKey: String get() = id.name

workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/SimpleLoggingWorkflowInterceptorTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.squareup.workflow1
33
import com.squareup.workflow1.WorkflowInterceptor.WorkflowSession
44
import kotlinx.coroutines.CoroutineScope
55
import kotlinx.coroutines.cancel
6+
import kotlin.coroutines.CoroutineContext
67
import kotlin.coroutines.EmptyCoroutineContext
78
import kotlin.reflect.KType
89
import kotlin.reflect.typeOf
@@ -90,6 +91,7 @@ internal class SimpleLoggingWorkflowInterceptorTest {
9091
override val parent: WorkflowSession? get() = null
9192
override val runtimeConfig: RuntimeConfig = RuntimeConfigOptions.DEFAULT_CONFIG
9293
override val workflowTracer: WorkflowTracer? = null
94+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
9395
}
9496

9597
private object FakeRenderContext : BaseRenderContext<Unit, Unit, Nothing> {

workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/WorkflowInterceptorTest.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,7 @@ internal class WorkflowInterceptorTest {
183183
override val parent: WorkflowSession? = null
184184
override val runtimeConfig: RuntimeConfig = RuntimeConfigOptions.DEFAULT_CONFIG
185185
override val workflowTracer: WorkflowTracer? = null
186+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
186187
}
187188

188189
private object TestWorkflow : StatefulWorkflow<String, String, String, String>() {

workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/ChainedWorkflowInterceptorTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import kotlinx.coroutines.Job
2424
import kotlinx.coroutines.launch
2525
import kotlinx.coroutines.test.advanceUntilIdle
2626
import kotlinx.coroutines.test.runTest
27+
import kotlin.coroutines.CoroutineContext
2728
import kotlin.coroutines.EmptyCoroutineContext
2829
import kotlin.reflect.KType
2930
import kotlin.test.Test
@@ -359,5 +360,6 @@ internal class ChainedWorkflowInterceptorTest {
359360
override val parent: WorkflowSession? = null
360361
override val runtimeConfig: RuntimeConfig = RuntimeConfigOptions.DEFAULT_CONFIG
361362
override val workflowTracer: WorkflowTracer? = null
363+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
362364
}
363365
}

workflow-runtime/src/commonTest/kotlin/com/squareup/workflow1/internal/WorkflowNodeTest.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
4242
import kotlinx.coroutines.test.runTest
4343
import kotlinx.coroutines.withTimeout
4444
import kotlin.coroutines.CoroutineContext
45+
import kotlin.coroutines.EmptyCoroutineContext
4546
import kotlin.reflect.typeOf
4647
import kotlin.test.AfterTest
4748
import kotlin.test.Test
@@ -1418,5 +1419,6 @@ internal class WorkflowNodeTest {
14181419
override val parent: WorkflowSession? = null
14191420
override val runtimeConfig: RuntimeConfig = RuntimeConfigOptions.DEFAULT_CONFIG
14201421
override val workflowTracer: WorkflowTracer? = null
1422+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
14211423
}
14221424
}

workflow-tracing-papa/src/test/java/com/squareup/workflow1/tracing/papa/WorkflowPapaTracerTest.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import com.squareup.workflow1.tracing.RuntimeTraceContext
1616
import com.squareup.workflow1.tracing.RuntimeUpdateLogLine
1717
import com.squareup.workflow1.tracing.WorkflowSessionInfo
1818
import kotlinx.coroutines.test.TestScope
19+
import kotlin.coroutines.CoroutineContext
20+
import kotlin.coroutines.EmptyCoroutineContext
1921
import kotlin.test.Test
2022
import kotlin.test.assertEquals
2123
import kotlin.test.assertNotNull
@@ -246,7 +248,8 @@ internal class WorkflowPapaTracerTest {
246248
private val workflow: TestWorkflow,
247249
override val sessionId: Long,
248250
override val renderKey: String,
249-
override val parent: WorkflowSession?
251+
override val parent: WorkflowSession?,
252+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
250253
) : WorkflowSession {
251254
override val identifier = workflow.identifier
252255
override val runtimeConfig = TestRuntimeConfig()

workflow-tracing/src/main/java/com/squareup/workflow1/tracing/ConfigSnapshot.kt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,18 @@ import com.squareup.workflow1.RuntimeConfigOptions.RENDER_ONLY_WHEN_STATE_CHANGE
88
import com.squareup.workflow1.RuntimeConfigOptions.STABLE_EVENT_HANDLERS
99
import com.squareup.workflow1.RuntimeConfigOptions.WORK_STEALING_DISPATCHER
1010
import com.squareup.workflow1.WorkflowExperimentalRuntime
11+
import kotlinx.coroutines.CoroutineDispatcher
1112

1213
/**
1314
* Snapshot of the current [RuntimeConfig]
1415
*/
1516
@OptIn(WorkflowExperimentalRuntime::class)
16-
public class ConfigSnapshot(config: RuntimeConfig) {
17-
public val configAsString: String = config.toString()
17+
public class ConfigSnapshot(
18+
config: RuntimeConfig,
19+
public val runtimeDispatch: CoroutineDispatcher? = null
20+
) {
21+
22+
public val configAsString: String = "$config, $runtimeDispatch"
1823

1924
public val shortConfigAsString: String by lazy {
2025
buildString {
@@ -40,6 +45,7 @@ public class ConfigSnapshot(config: RuntimeConfig) {
4045
if (config.isEmpty()) {
4146
append("Base, ")
4247
}
48+
append("Dispatch: ${runtimeDispatch?.toString()?.take(6)}")
4349
}
4450
}
4551
}

workflow-tracing/src/main/java/com/squareup/workflow1/tracing/WorkflowRuntimeMonitor.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import com.squareup.workflow1.tracing.RenderCause.RootPropsChanged
2929
import com.squareup.workflow1.tracing.RenderCause.WaitingForOutput
3030
import com.squareup.workflow1.tracing.WorkflowRuntimeMonitor.ActionType.CascadeAction
3131
import com.squareup.workflow1.tracing.WorkflowRuntimeMonitor.ActionType.QueuedAction
32+
import kotlinx.coroutines.CoroutineDispatcher
3233
import kotlinx.coroutines.CoroutineScope
3334
import kotlinx.coroutines.Job
3435
import kotlin.time.Duration.Companion.nanoseconds
@@ -105,7 +106,7 @@ public class WorkflowRuntimeMonitor(
105106

106107
if (session.isRootWorkflow) {
107108
// Cache the config snapshot for this whole runtime.
108-
configSnapshot = ConfigSnapshot(session.runtimeConfig)
109+
configSnapshot = ConfigSnapshot(session.runtimeConfig, session.runtimeContext[CoroutineDispatcher])
109110
check(renderIncomingCauses.isEmpty()) {
110111
"Workflow runtime for $runtimeName already has incoming render on creation triggered by " +
111112
"${renderIncomingCauses.lastOrNull()}"

workflow-tracing/src/test/java/com/squareup/workflow1/tracing/WorkflowRuntimeMonitorTest.kt

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ import com.squareup.workflow1.identifier
2121
import com.squareup.workflow1.tracing.RenderCause.RootCreation
2222
import com.squareup.workflow1.tracing.RenderCause.RootPropsChanged
2323
import kotlinx.coroutines.CoroutineScope
24+
import kotlinx.coroutines.ExperimentalCoroutinesApi
2425
import kotlinx.coroutines.test.TestScope
26+
import kotlinx.coroutines.test.UnconfinedTestDispatcher
27+
import kotlin.coroutines.CoroutineContext
28+
import kotlin.coroutines.EmptyCoroutineContext
2529
import kotlin.reflect.KType
2630
import kotlin.test.Test
2731
import kotlin.test.assertContains
@@ -74,6 +78,23 @@ internal class WorkflowRuntimeMonitorTest {
7478
assertTrue(monitor.renderIncomingCauses.first() is RootCreation)
7579
}
7680

81+
@OptIn(ExperimentalCoroutinesApi::class)
82+
@Test
83+
fun `onSessionStarted captures runtime context`() {
84+
val monitor = WorkflowRuntimeMonitor(
85+
runtimeName = runtimeName,
86+
workflowRuntimeTracers = listOf(fakeRuntimeTracer)
87+
)
88+
val testWorkflow = TestWorkflow()
89+
val testCoroutineDispatcher = UnconfinedTestDispatcher()
90+
val rootSession = testWorkflow.createRootSession(testCoroutineDispatcher)
91+
val testScope = TestScope(testCoroutineDispatcher)
92+
93+
monitor.onSessionStarted(testScope, rootSession)
94+
95+
assertEquals(testCoroutineDispatcher, monitor.configSnapshot.runtimeDispatch)
96+
}
97+
7798
@Test
7899
fun `onSessionStarted handles child workflow session`() {
79100
val monitor = WorkflowRuntimeMonitor(
@@ -647,26 +668,33 @@ internal class WorkflowRuntimeMonitorTest {
647668

648669
override fun snapshotState(state: String): Snapshot = Snapshot.of(state)
649670

650-
fun createRootSession(): WorkflowSession = TestWorkflowSession(
651-
workflow = this,
652-
sessionId = 1L,
653-
renderKey = "root",
654-
parent = null
655-
)
656-
657-
fun createChildSession(parent: WorkflowSession): WorkflowSession = TestWorkflowSession(
671+
fun createRootSession(context: CoroutineContext = EmptyCoroutineContext): WorkflowSession =
672+
TestWorkflowSession(
673+
workflow = this,
674+
sessionId = 1L,
675+
renderKey = "root",
676+
parent = null,
677+
runtimeContext = context
678+
)
679+
680+
fun createChildSession(
681+
parent: WorkflowSession,
682+
context: CoroutineContext = EmptyCoroutineContext
683+
): WorkflowSession = TestWorkflowSession(
658684
workflow = this,
659685
sessionId = 2L,
660686
renderKey = "child",
661-
parent = parent
687+
parent = parent,
688+
runtimeContext = context
662689
)
663690
}
664691

665692
private class TestWorkflowSession(
666693
private val workflow: TestWorkflow,
667694
override val sessionId: Long,
668695
override val renderKey: String,
669-
override val parent: WorkflowSession?
696+
override val parent: WorkflowSession?,
697+
override val runtimeContext: CoroutineContext = EmptyCoroutineContext
670698
) : WorkflowSession {
671699
override val identifier = workflow.identifier
672700
override val runtimeConfig = TestRuntimeConfig()

0 commit comments

Comments
 (0)