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

Fix nullability problem wrt return type of kotlin services #331

Merged
merged 1 commit into from
May 27, 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
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ class CodegenTest : TestDefinitions.TestSuite {
// Just needs to compile
return CodegenTestCornerCasesClient.fromContext(context, request)._send("my_send").await()
}

@Exclusive
suspend fun returnNull(context: ObjectContext, request: String?): String? {
return CodegenTestCornerCasesClient.fromContext(context, context.key())
.returnNull(request)
.await()
}
}

@Workflow
Expand Down Expand Up @@ -280,6 +287,20 @@ class CodegenTest : TestDefinitions.TestSuite {
invokeMessage(
Target.service("RawInputOutput", "rawOutputWithCustomCT"), KtSerdes.UNIT, null),
outputMessage("{{".toByteArray()),
END_MESSAGE))
END_MESSAGE),
testInvocation({ CornerCases() }, "returnNull")
.withInput(
startMessage(1, "mykey"),
inputMessage(KtSerdes.json<String?>().serialize(null)),
completionMessage(1, KtSerdes.json<String?>(), null))
.onlyUnbuffered()
.expectingOutput(
invokeMessage(
Target.virtualObject("CodegenTestCornerCases", "mykey", "returnNull"),
KtSerdes.json<String?>(),
null),
outputMessage(KtSerdes.json<String?>(), null),
END_MESSAGE),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ internal class SingleAwaitableImpl<T : Any?>(
}
}

internal abstract class BaseSingleMappedAwaitableImpl<T : Any, U : Any>(
internal abstract class BaseSingleMappedAwaitableImpl<T : Any?, U : Any?>(
private val inner: BaseAwaitableImpl<T>
) : BaseAwaitableImpl<U>(inner.syscalls) {
private var mappedResult: Result<U>? = null
Expand All @@ -76,7 +76,7 @@ internal abstract class BaseSingleMappedAwaitableImpl<T : Any, U : Any>(
}
}

internal open class SingleSerdeAwaitableImpl<T : Any>
internal open class SingleSerdeAwaitableImpl<T : Any?>
internal constructor(
syscalls: Syscalls,
deferred: Deferred<ByteBuffer>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ internal class ContextImpl internal constructor(private val syscalls: Syscalls)
}

override suspend fun <T : Any> set(key: StateKey<T>, value: T) {
val serializedValue = key.serde().serializeWrappingException(syscalls, value)!!
val serializedValue = key.serde().serializeWrappingException(syscalls, value)
return suspendCancellableCoroutine { cont: CancellableContinuation<Unit> ->
syscalls.set(key.name(), serializedValue, completingUnitContinuation(cont))
}
Expand All @@ -101,7 +101,7 @@ internal class ContextImpl internal constructor(private val syscalls: Syscalls)
return UnitAwakeableImpl(syscalls, deferred)
}

override suspend fun <T : Any, R : Any> callAsync(
override suspend fun <T : Any?, R : Any?> callAsync(
target: Target,
inputSerde: Serde<T>,
outputSerde: Serde<R>,
Expand All @@ -117,7 +117,7 @@ internal class ContextImpl internal constructor(private val syscalls: Syscalls)
return SingleSerdeAwaitableImpl(syscalls, deferred, outputSerde)
}

override suspend fun <T : Any> send(
override suspend fun <T : Any?> send(
target: Target,
inputSerde: Serde<T>,
parameter: T,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import java.nio.charset.StandardCharsets
import kotlin.reflect.typeOf
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.serializer

object KtStateKey {
Expand All @@ -29,15 +30,15 @@ object KtStateKey {
object KtDurablePromiseKey {

/** Creates a json [StateKey]. */
inline fun <reified T> json(name: String): DurablePromiseKey<T> {
inline fun <reified T : Any?> json(name: String): DurablePromiseKey<T> {
return DurablePromiseKey.of(name, KtSerdes.json())
}
}

object KtSerdes {

/** Creates a [Serde] implementation using the `kotlinx.serialization` json module. */
inline fun <reified T> json(): Serde<T> {
inline fun <reified T : Any?> json(): Serde<T> {
@Suppress("UNCHECKED_CAST")
return when (typeOf<T>()) {
typeOf<Unit>() -> UNIT as Serde<T>
Expand Down Expand Up @@ -69,10 +70,13 @@ object KtSerdes {
}

/** Creates a [Serde] implementation using the `kotlinx.serialization` json module. */
fun <T> json(serializer: KSerializer<T>): Serde<T> {
fun <T : Any?> json(serializer: KSerializer<T>): Serde<T> {
return object : Serde<T> {
override fun serialize(value: T): ByteArray {
return Json.encodeToString(serializer, value!!).encodeToByteArray()
override fun serialize(value: T?): ByteArray {
if (value == null) {
return Json.encodeToString(JsonNull.serializer(), JsonNull).encodeToByteArray()
}
return Json.encodeToString(serializer, value).encodeToByteArray()
}

override fun deserialize(value: ByteArray): T {
Expand Down
6 changes: 3 additions & 3 deletions sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ sealed interface Context {
* @param parameter the invocation request parameter.
* @return the invocation response.
*/
suspend fun <T : Any, R : Any> call(
suspend fun <T : Any?, R : Any?> call(
target: Target,
inputSerde: Serde<T>,
outputSerde: Serde<R>,
Expand All @@ -75,7 +75,7 @@ sealed interface Context {
* @param parameter the invocation request parameter.
* @return an [Awaitable] that wraps the Restate service method result.
*/
suspend fun <T : Any, R : Any> callAsync(
suspend fun <T : Any?, R : Any?> callAsync(
target: Target,
inputSerde: Serde<T>,
outputSerde: Serde<R>,
Expand All @@ -90,7 +90,7 @@ sealed interface Context {
* @param parameter the invocation request parameter.
* @param delay time to wait before executing the call
*/
suspend fun <T : Any> send(
suspend fun <T : Any?> send(
target: Target,
inputSerde: Serde<T>,
parameter: T,
Expand Down
Loading