From a14b08d4c99c01012a0f24028525591456b051e4 Mon Sep 17 00:00:00 2001 From: Pierre-Yves Ricau Date: Wed, 4 Dec 2024 11:25:31 -0800 Subject: [PATCH] Add smol caching & a utility method --- .../squareup/workflow1/WorkflowIdentifier.kt | 29 ++++++++++++++----- .../workflow1/WorkflowIdentifierTest.kt | 8 ++--- .../squareup/workflow1/WorkflowInterceptor.kt | 6 ++++ .../workflow1/testing/RealRenderTester.kt | 4 +-- .../tracing/TracingWorkflowInterceptor.kt | 2 +- 5 files changed, 34 insertions(+), 15 deletions(-) diff --git a/workflow-core/src/commonMain/kotlin/com/squareup/workflow1/WorkflowIdentifier.kt b/workflow-core/src/commonMain/kotlin/com/squareup/workflow1/WorkflowIdentifier.kt index 06ebb9392..1607cabb2 100644 --- a/workflow-core/src/commonMain/kotlin/com/squareup/workflow1/WorkflowIdentifier.kt +++ b/workflow-core/src/commonMain/kotlin/com/squareup/workflow1/WorkflowIdentifier.kt @@ -9,6 +9,7 @@ import okio.Buffer import okio.ByteString import okio.EOFException import kotlin.LazyThreadSafetyMode.PUBLICATION +import kotlin.concurrent.Volatile import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmName import kotlin.reflect.KClass @@ -58,6 +59,17 @@ public class WorkflowIdentifier internal constructor( private val proxiedIdentifiers = generateSequence(this) { it.proxiedIdentifier } + @Volatile + private var cachedToString: String? = null + + /** + * Either a [KClass] or [KType] representing the "real" type that this identifier + * identifies – i.e. which is not an [ImpostorWorkflow]. + */ + public val realIdentifierType: WorkflowIdentifierType by lazy(PUBLICATION) { + proxiedIdentifiers.last().type + } + /** * If this identifier is snapshottable, returns the serialized form of the identifier. * If it is not snapshottable, returns null. @@ -83,11 +95,8 @@ public class WorkflowIdentifier internal constructor( } } - /** - * Returns either a [KClass] or [KType] representing the "real" type that this identifier - * identifies – i.e. which is not an [ImpostorWorkflow]. - */ - public fun getRealIdentifierType(): WorkflowIdentifierType = proxiedIdentifiers.last().type + @Deprecated("This is now a lazily computed val", ReplaceWith("realIdentifierType")) + public fun getRealIdentifierType(): WorkflowIdentifierType = realIdentifierType /** * If this identifier identifies an [ImpostorWorkflow], returns the result of that workflow's @@ -95,11 +104,15 @@ public class WorkflowIdentifier internal constructor( * identifier including the name of its workflow type and any [ImpostorWorkflow.realIdentifier]s. * */ - override fun toString(): String = - description?.invoke() + override fun toString(): String { + return cachedToString ?: (description?.invoke() ?: proxiedIdentifiers .joinToString { it.typeName } - .let { "WorkflowIdentifier($it)" } + .let { "WorkflowIdentifier($it)" }) + .also { + cachedToString = it + } + } override fun equals(other: Any?): Boolean = when { this === other -> true diff --git a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkflowIdentifierTest.kt b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkflowIdentifierTest.kt index e83db8820..bc947edc3 100644 --- a/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkflowIdentifierTest.kt +++ b/workflow-core/src/commonTest/kotlin/com/squareup/workflow1/WorkflowIdentifierTest.kt @@ -153,22 +153,22 @@ internal class WorkflowIdentifierTest { @Test fun getRealIdentifierType_returns_self_for_non_impostor_workflow() { val id = TestWorkflow1.identifier - assertEquals(Snapshottable(TestWorkflow1::class), id.getRealIdentifierType()) + assertEquals(Snapshottable(TestWorkflow1::class), id.realIdentifierType) } @Test fun getRealIdentifierType_returns_real_identifier_for_impostor_workflow() { val id = TestImpostor1(TestWorkflow1).identifier - assertEquals(Snapshottable(TestWorkflow1::class), id.getRealIdentifierType()) + assertEquals(Snapshottable(TestWorkflow1::class), id.realIdentifierType) } @Test fun getRealIdentifierType_returns_leaf_real_identifier_for_impostor_workflow_chain() { val id = TestImpostor2(TestImpostor1(TestWorkflow1)).identifier - assertEquals(Snapshottable(TestWorkflow1::class), id.getRealIdentifierType()) + assertEquals(Snapshottable(TestWorkflow1::class), id.realIdentifierType) } @Test fun getRealIdentifierType_returns_KType_of_unsnapshottable_identifier() { val id = TestUnsnapshottableImpostor(typeOf>()).identifier - assertEquals(Unsnapshottable(typeOf>()), id.getRealIdentifierType()) + assertEquals(Unsnapshottable(typeOf>()), id.realIdentifierType) } public object TestWorkflow1 : Workflow { diff --git a/workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/WorkflowInterceptor.kt b/workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/WorkflowInterceptor.kt index 742ac38a2..2363b7ad9 100644 --- a/workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/WorkflowInterceptor.kt +++ b/workflow-runtime/src/commonMain/kotlin/com/squareup/workflow1/WorkflowInterceptor.kt @@ -152,6 +152,12 @@ public interface WorkflowInterceptor { /** The parent [WorkflowSession] of this workflow, or null if this is the root workflow. */ public val parent: WorkflowSession? + /** + * true if this is the root workflow, in which case [parent] is null. + */ + public val isRootWorkflow: Boolean + get() = parent == null + /** The [RuntimeConfig] of the runtime this session is executing in. */ public val runtimeConfig: RuntimeConfig } diff --git a/workflow-testing/src/main/java/com/squareup/workflow1/testing/RealRenderTester.kt b/workflow-testing/src/main/java/com/squareup/workflow1/testing/RealRenderTester.kt index efe4b1233..c513a6475 100644 --- a/workflow-testing/src/main/java/com/squareup/workflow1/testing/RealRenderTester.kt +++ b/workflow-testing/src/main/java/com/squareup/workflow1/testing/RealRenderTester.kt @@ -360,8 +360,8 @@ internal fun createRenderChildInvocation( internal fun WorkflowIdentifier.realTypeMatchesExpectation( expected: WorkflowIdentifier ): Boolean { - val expectedType = expected.getRealIdentifierType() - val actualType = getRealIdentifierType() + val expectedType = expected.realIdentifierType + val actualType = realIdentifierType return actualType.matchesExpectation(expectedType) } diff --git a/workflow-tracing/src/main/java/com/squareup/workflow1/diagnostic/tracing/TracingWorkflowInterceptor.kt b/workflow-tracing/src/main/java/com/squareup/workflow1/diagnostic/tracing/TracingWorkflowInterceptor.kt index d17a73a58..4fbaec777 100644 --- a/workflow-tracing/src/main/java/com/squareup/workflow1/diagnostic/tracing/TracingWorkflowInterceptor.kt +++ b/workflow-tracing/src/main/java/com/squareup/workflow1/diagnostic/tracing/TracingWorkflowInterceptor.kt @@ -494,7 +494,7 @@ public class TracingWorkflowInterceptor internal constructor( } private fun WorkflowIdentifier.toLoggingName(): String { - val type = getRealIdentifierType() + val type = realIdentifierType return when { type is Snapshottable && type.kClass != null -> type.kClass!!.toLoggingName() type is Unsnapshottable -> type.kType.toLoggingName()