Skip to content
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

Add smol caching & a utility method #1239

Merged
merged 3 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions workflow-core/api/workflow-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ public final class com/squareup/workflow1/WorkflowIdentifier {
public static final field Companion Lcom/squareup/workflow1/WorkflowIdentifier$Companion;
public fun equals (Ljava/lang/Object;)Z
public final fun getRealIdentifierType ()Lcom/squareup/workflow1/WorkflowIdentifierType;
public final fun getRealType ()Lcom/squareup/workflow1/WorkflowIdentifierType;
public fun hashCode ()I
public final fun toByteStringOrNull ()Lokio/ByteString;
public fun toString ()Ljava/lang/String;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 realType: 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.
Expand All @@ -83,23 +95,26 @@ 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("realType"))
public fun getRealIdentifierType(): WorkflowIdentifierType = realType

/**
* If this identifier identifies an [ImpostorWorkflow], returns the result of that workflow's
* [ImpostorWorkflow.describeRealIdentifier] method, otherwise returns a description of this
* identifier including the name of its workflow type and any [ImpostorWorkflow.realIdentifier]s.
*
*/
override fun toString(): String =
description?.invoke()
?: proxiedIdentifiers
.joinToString { it.typeName }
.let { "WorkflowIdentifier($it)" }
override fun toString(): String {
return cachedToString ?: (
description?.invoke()
?: proxiedIdentifiers
.joinToString { it.typeName }
.let { "WorkflowIdentifier($it)" }
)
.also {
cachedToString = it
}
}

override fun equals(other: Any?): Boolean = when {
this === other -> true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.realType)
}

@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.realType)
}

@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.realType)
}

@Test fun getRealIdentifierType_returns_KType_of_unsnapshottable_identifier() {
val id = TestUnsnapshottableImpostor(typeOf<List<String>>()).identifier
assertEquals(Unsnapshottable(typeOf<List<String>>()), id.getRealIdentifierType())
assertEquals(Unsnapshottable(typeOf<List<String>>()), id.realType)
}

public object TestWorkflow1 : Workflow<Nothing, Nothing, Nothing> {
Expand Down
5 changes: 5 additions & 0 deletions workflow-runtime/api/workflow-runtime.api
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,10 @@ public abstract interface class com/squareup/workflow1/WorkflowInterceptor$Workf
public abstract fun getRenderKey ()Ljava/lang/String;
public abstract fun getRuntimeConfig ()Ljava/util/Set;
public abstract fun getSessionId ()J
public abstract fun isRootWorkflow ()Z
}

public final class com/squareup/workflow1/WorkflowInterceptor$WorkflowSession$DefaultImpls {
public static fun isRootWorkflow (Lcom/squareup/workflow1/WorkflowInterceptor$WorkflowSession;)Z
}

Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -360,8 +360,8 @@ internal fun createRenderChildInvocation(
internal fun WorkflowIdentifier.realTypeMatchesExpectation(
expected: WorkflowIdentifier
): Boolean {
val expectedType = expected.getRealIdentifierType()
val actualType = getRealIdentifierType()
val expectedType = expected.realType
val actualType = realType
return actualType.matchesExpectation(expectedType)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ public class TracingWorkflowInterceptor internal constructor(
}

private fun WorkflowIdentifier.toLoggingName(): String {
val type = getRealIdentifierType()
val type = realType
return when {
type is Snapshottable && type.kClass != null -> type.kClass!!.toLoggingName()
type is Unsnapshottable -> type.kType.toLoggingName()
Expand Down
Loading