diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 473211f0..d1df344f 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -15,7 +15,7 @@ jobs: strategy: fail-fast: false matrix: - java: [ 17, 21 ] + java: [ 17, 21, 25 ] steps: - uses: actions/checkout@v4 - name: Set up JDK ${{ matrix.java }} diff --git a/build.gradle.kts b/build.gradle.kts index c4e60df9..6dd8587c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -65,7 +65,10 @@ allprojects { filters = arrayOf( com.github.jk1.license.filter.LicenseBundleNormalizer( - "$rootDir/config/license-normalizer-bundle.json", true)) + "$rootDir/config/license-normalizer-bundle.json", + true, + ) + ) } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 002f2bc2..c7601701 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -11,5 +11,5 @@ repositories { dependencies { implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.2.10") implementation("org.jetbrains.kotlin:kotlin-serialization:2.2.10") - implementation("com.diffplug.spotless:spotless-plugin-gradle:7.2.1") + implementation("com.diffplug.spotless:spotless-plugin-gradle:8.2.0") } \ No newline at end of file diff --git a/bytebuddy-proxy-support/build.gradle.kts b/bytebuddy-proxy-support/build.gradle.kts index 837261a9..b36f8cda 100644 --- a/bytebuddy-proxy-support/build.gradle.kts +++ b/bytebuddy-proxy-support/build.gradle.kts @@ -16,6 +16,7 @@ dependencies { testImplementation(libs.junit.jupiter) testImplementation(libs.assertj) + testRuntimeOnly(libs.junit.platform.launcher) } tasks.withType { isFailOnError = false } diff --git a/client-kotlin/src/main/kotlin/dev/restate/client/kotlin/ingress.kt b/client-kotlin/src/main/kotlin/dev/restate/client/kotlin/ingress.kt index b74bd299..cc0e8381 100644 --- a/client-kotlin/src/main/kotlin/dev/restate/client/kotlin/ingress.kt +++ b/client-kotlin/src/main/kotlin/dev/restate/client/kotlin/ingress.kt @@ -56,7 +56,7 @@ suspend fun Client.callSuspend(request: Request): Response< */ suspend fun Request.send( client: Client, - delay: Duration? = null + delay: Duration? = null, ): SendResponse { return client.sendSuspend(this, delay) } @@ -67,7 +67,7 @@ suspend fun Request.send( */ suspend fun Client.sendSuspend( request: Request, - delay: Duration? = null + delay: Duration? = null, ): SendResponse { return this.sendAsync(request, delay?.toJavaDuration()).await() } @@ -81,7 +81,7 @@ suspend fun Client.sendSuspend( */ suspend fun WorkflowRequest.submit( client: Client, - delay: Duration? = null + delay: Duration? = null, ): SendResponse { return client.submitSuspend(this, delay) } @@ -89,7 +89,7 @@ suspend fun WorkflowRequest.submit( /** Submit a workflow, optionally providing an execution delay to wait for. */ suspend fun Client.submitSuspend( request: WorkflowRequest, - delay: Duration? = null + delay: Duration? = null, ): SendResponse { return this.submitAsync(request, delay?.toJavaDuration()).await() } @@ -104,7 +104,7 @@ suspend fun Client.submitSuspend( suspend fun Client.AwakeableHandle.resolveSuspend( typeTag: TypeTag, payload: T, - options: RequestOptions = RequestOptions.DEFAULT + options: RequestOptions = RequestOptions.DEFAULT, ): Response { return this.resolveAsync(typeTag, payload, options).await() } @@ -117,7 +117,7 @@ suspend fun Client.AwakeableHandle.resolveSuspend( */ suspend inline fun Client.AwakeableHandle.resolveSuspend( payload: T, - options: RequestOptions = RequestOptions.DEFAULT + options: RequestOptions = RequestOptions.DEFAULT, ): Response { return this.resolveSuspend(typeTag(), payload, options) } @@ -130,7 +130,7 @@ suspend inline fun Client.AwakeableHandle.resolveSuspend( */ suspend fun Client.AwakeableHandle.rejectSuspend( reason: String, - options: RequestOptions = RequestOptions.DEFAULT + options: RequestOptions = RequestOptions.DEFAULT, ): Response { return this.rejectAsync(reason, options).await() } @@ -180,7 +180,7 @@ suspend fun Client.InvocationHandle.getOutputSuspend( */ inline fun Client.idempotentInvocationHandle( target: Target, - idempotencyKey: String + idempotencyKey: String, ): Client.IdempotentInvocationHandle { return this.idempotentInvocationHandle(target, idempotencyKey, typeTag()) } @@ -218,7 +218,7 @@ suspend fun Client.IdempotentInvocationHandle.getOutputSuspend( */ inline fun Client.workflowHandle( workflowName: String, - workflowId: String + workflowId: String, ): Client.WorkflowHandle { return this.workflowHandle(workflowName, workflowId, typeTag()) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e8f27214..1bf85687 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -58,6 +58,11 @@ [libraries.junit-jupiter.version] ref = 'junit' + [libraries.junit-platform-launcher] + module = 'org.junit.platform:junit-platform-launcher' + # TODO align this with ref = junit once bumped to junit 6 + version = '1.14.2' + [libraries.kotlinx-coroutines-core] module = 'org.jetbrains.kotlinx:kotlinx-coroutines-core' @@ -209,7 +214,7 @@ jib = 'com.google.cloud.tools.jib:3.4.5' jsonschema2pojo = 'org.jsonschema2pojo:1.2.2' nexus-publish = 'io.github.gradle-nexus.publish-plugin:1.3.0' - openapi-generator = 'org.openapi.generator:7.5.0' + openapi-generator = 'org.openapi.generator:7.17.0' protobuf = 'com.google.protobuf:0.9.4' shadow = 'com.gradleup.shadow:9.0.0-beta8' spotless = 'com.diffplug.spotless:7.2.1' @@ -223,7 +228,7 @@ [versions] jackson = '2.18.4' - junit = '5.10.2' + junit = '5.14.1' kotlinx-coroutines = '1.10.2' kotlinx-serialization = '1.9.0' ksp = '2.2.10-2.0.2' diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index a4b76b95..f8e1ee31 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d4081da4..19a6bdeb 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.3.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index f3b75f3b..adff685a 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright © 2015-2021 the original authors. +# Copyright © 2015 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -114,7 +114,6 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. @@ -172,7 +171,6 @@ fi # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) @@ -205,15 +203,14 @@ fi DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # and any embedded shellness will be escaped. # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be # treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 9d21a218..c4bdd3ab 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -70,11 +70,10 @@ goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/KElementConverter.kt b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/KElementConverter.kt index d94ec33a..64c20a94 100644 --- a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/KElementConverter.kt +++ b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/KElementConverter.kt @@ -27,13 +27,17 @@ import kotlin.reflect.KClass class KElementConverter( private val logger: KSPLogger, private val builtIns: KSBuiltIns, - private val byteArrayType: KSType + private val byteArrayType: KSType, ) : KSDefaultVisitor() { companion object { private val SUPPORTED_CLASS_KIND: Set = setOf(ClassKind.CLASS, ClassKind.INTERFACE) private val EMPTY_PAYLOAD: PayloadType = PayloadType( - true, "", "Unit", "dev.restate.serde.kotlinx.KotlinSerializationSerdeFactory.UNIT") + true, + "", + "Unit", + "dev.restate.serde.kotlinx.KotlinSerializationSerdeFactory.UNIT", + ) private const val RAW_SERDE: String = "dev.restate.serde.Serde.RAW" } @@ -42,7 +46,8 @@ class KElementConverter( override fun visitAnnotated(annotated: KSAnnotated, data: Service.Builder) { if (annotated !is KSClassDeclaration) { logger.error( - "Only classes or interfaces can be annotated with @Service or @VirtualObject or @Workflow") + "Only classes or interfaces can be annotated with @Service or @VirtualObject or @Workflow" + ) } visitClassDeclaration(annotated as KSClassDeclaration, data) } @@ -56,7 +61,8 @@ class KElementConverter( if (!SUPPORTED_CLASS_KIND.contains(classDeclaration.classKind)) { logger.error( "The ServiceProcessor supports only class declarations of kind $SUPPORTED_CLASS_KIND", - classDeclaration) + classDeclaration, + ) } if (classDeclaration.getVisibility() == Visibility.PRIVATE) { logger.error("The annotated class is private", classDeclaration) @@ -94,7 +100,8 @@ class KElementConverter( if (data.handlers.isEmpty()) { logger.warn( "The class declaration $targetFqcn has no methods annotated as handlers", - classDeclaration) + classDeclaration, + ) } var serdeFactoryDecl = "dev.restate.serde.kotlinx.KotlinSerializationSerdeFactory()" @@ -134,7 +141,8 @@ class KElementConverter( if (!(!hasAnyAnnotation || hasExactlyOneAnnotation)) { logger.error( "You can have only one annotation between @Shared and @Exclusive and @Workflow to a method", - function) + function, + ) } val handlerBuilder = Handler.builder() @@ -158,7 +166,8 @@ class KElementConverter( .withInputAccept(inputAcceptFromParameterList(function.parameters)) .withInputType(inputPayloadFromParameterList(function.parameters)) .withOutputType(outputPayloadFromExecutableElement(function)) - .validateAndBuild()) + .validateAndBuild() + ) } catch (e: Exception) { logger.error("Error when building handler: $e", function) } @@ -184,7 +193,8 @@ class KElementConverter( parameterElement.type.resolve(), parameterElement.getAnnotationsByType(Json::class).firstOrNull(), parameterElement.getAnnotationsByType(Raw::class).firstOrNull(), - parameterElement) + parameterElement, + ) } @OptIn(KspExperimental::class) @@ -193,14 +203,15 @@ class KElementConverter( fn.returnType?.resolve() ?: builtIns.unitType, fn.getAnnotationsByType(Json::class).firstOrNull(), fn.getAnnotationsByType(Raw::class).firstOrNull(), - fn) + fn, + ) } private fun payloadFromTypeMirrorAndAnnotations( ty: KSType, jsonAnnotation: Json?, rawAnnotation: Raw?, - relatedNode: KSNode + relatedNode: KSNode, ): PayloadType { if (ty == builtIns.unitType) { if (rawAnnotation != null || jsonAnnotation != null) { @@ -222,12 +233,16 @@ class KElementConverter( val qualifiedTypeName = qualifiedTypeName(ty) var serdeDecl: String = if (rawAnnotation != null) RAW_SERDE else jsonSerdeDecl(ty, qualifiedTypeName) - if (rawAnnotation != null && - rawAnnotation.contentType != getAnnotationDefaultValue(Raw::class.java, "contentType")) { + if ( + rawAnnotation != null && + rawAnnotation.contentType != getAnnotationDefaultValue(Raw::class.java, "contentType") + ) { serdeDecl = contentTypeDecoratedSerdeDecl(serdeDecl, rawAnnotation.contentType) } - if (jsonAnnotation != null && - jsonAnnotation.contentType != getAnnotationDefaultValue(Json::class.java, "contentType")) { + if ( + jsonAnnotation != null && + jsonAnnotation.contentType != getAnnotationDefaultValue(Json::class.java, "contentType") + ) { serdeDecl = contentTypeDecoratedSerdeDecl(serdeDecl, jsonAnnotation.contentType) } @@ -249,12 +264,13 @@ class KElementConverter( private fun validateMethodSignature( serviceType: ServiceType, handlerType: HandlerType, - function: KSFunctionDeclaration + function: KSFunctionDeclaration, ) { if (function.parameters.isEmpty()) { logger.error( "The annotated method has no parameters. There must be at least the context parameter as first parameter", - function) + function, + ) } when (handlerType) { HandlerType.SHARED -> @@ -265,7 +281,8 @@ class KElementConverter( } else { logger.error( "The annotation @Shared is not supported by the service type $serviceType", - function) + function, + ) } HandlerType.EXCLUSIVE -> if (serviceType == ServiceType.VIRTUAL_OBJECT) { @@ -273,7 +290,8 @@ class KElementConverter( } else { logger.error( "The annotation @Exclusive is not supported by the service type $serviceType", - function) + function, + ) } HandlerType.STATELESS -> validateFirstParameterType(Context::class, function) HandlerType.WORKFLOW -> @@ -282,17 +300,21 @@ class KElementConverter( } else { logger.error( "The annotation @Workflow is not supported by the service type $serviceType", - function) + function, + ) } } } private fun validateFirstParameterType(clazz: KClass<*>, function: KSFunctionDeclaration) { - if (function.parameters[0].type.resolve().declaration.qualifiedName!!.asString() != - clazz.qualifiedName) { + if ( + function.parameters[0].type.resolve().declaration.qualifiedName!!.asString() != + clazz.qualifiedName + ) { logger.error( "The method signature must have ${clazz.qualifiedName} as first parameter, was ${function.parameters[0].type.resolve().declaration.qualifiedName!!.asString()}", - function) + function, + ) } } diff --git a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/MetaRestateAnnotation.kt b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/MetaRestateAnnotation.kt index aa1351be..a7cffabe 100644 --- a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/MetaRestateAnnotation.kt +++ b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/MetaRestateAnnotation.kt @@ -14,7 +14,7 @@ import dev.restate.sdk.endpoint.definition.ServiceType internal data class MetaRestateAnnotation( val annotationName: KSName, - val serviceType: ServiceType + val serviceType: ServiceType, ) { fun resolveName(annotated: KSAnnotated): String? = annotated.annotations diff --git a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessor.kt b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessor.kt index b4bf50dc..16947cf7 100644 --- a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessor.kt +++ b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessor.kt @@ -31,7 +31,7 @@ import java.nio.charset.Charset class ServiceProcessor( private val logger: KSPLogger, private val codeGenerator: CodeGenerator, - private val options: AnnotationProcessingOptions + private val options: AnnotationProcessingOptions, ) : SymbolProcessor { companion object { @@ -45,8 +45,10 @@ class ServiceProcessor( mapOf( ServiceType.SERVICE to "templates/ServiceDefinitionFactory", ServiceType.WORKFLOW to "templates/ServiceDefinitionFactory", - ServiceType.VIRTUAL_OBJECT to "templates/ServiceDefinitionFactory"), - RESERVED_METHOD_NAMES) + ServiceType.VIRTUAL_OBJECT to "templates/ServiceDefinitionFactory", + ), + RESERVED_METHOD_NAMES, + ) private val clientCodegen: HandlebarsTemplateEngine = HandlebarsTemplateEngine( "Client", @@ -54,8 +56,10 @@ class ServiceProcessor( mapOf( ServiceType.SERVICE to "templates/Client", ServiceType.WORKFLOW to "templates/Client", - ServiceType.VIRTUAL_OBJECT to "templates/Client"), - RESERVED_METHOD_NAMES) + ServiceType.VIRTUAL_OBJECT to "templates/Client", + ), + RESERVED_METHOD_NAMES, + ) private val handlersCodegen: HandlebarsTemplateEngine = HandlebarsTemplateEngine( "Handlers", @@ -63,8 +67,10 @@ class ServiceProcessor( mapOf( ServiceType.SERVICE to "templates/Handlers", ServiceType.WORKFLOW to "templates/Handlers", - ServiceType.VIRTUAL_OBJECT to "templates/Handlers"), - RESERVED_METHOD_NAMES) + ServiceType.VIRTUAL_OBJECT to "templates/Handlers", + ), + RESERVED_METHOD_NAMES, + ) @OptIn(KspExperimental::class) override fun process(resolver: Resolver): List { @@ -72,7 +78,8 @@ class ServiceProcessor( KElementConverter( logger, resolver.builtIns, - resolver.getKotlinClassByName(ByteArray::class.qualifiedName!!)!!.asType(listOf())) + resolver.getKotlinClassByName(ByteArray::class.qualifiedName!!)!!.asType(listOf()), + ) val discovered = discoverRestateAnnotatedOrMetaAnnotatedServices(resolver) @@ -103,7 +110,8 @@ class ServiceProcessor( .createNewFile( Dependencies(false, service.first.containingFile!!), service.second.targetPkg.toString(), - name) + name, + ) .writer(Charset.defaultCharset()) } this.bindableServiceFactoryCodegen.generate(fileCreator, service.second) @@ -135,17 +143,21 @@ class ServiceProcessor( resolver .getClassDeclarationByName()!! .qualifiedName!!, - ServiceType.SERVICE), + ServiceType.SERVICE, + ), MetaRestateAnnotation( resolver .getClassDeclarationByName()!! .qualifiedName!!, - ServiceType.VIRTUAL_OBJECT), + ServiceType.VIRTUAL_OBJECT, + ), MetaRestateAnnotation( resolver .getClassDeclarationByName()!! .qualifiedName!!, - ServiceType.WORKFLOW)) + ServiceType.WORKFLOW, + ), + ) // Add spring annotations, if available resolver.getClassDeclarationByName("dev.restate.sdk.springboot.RestateService")?.let { @@ -153,7 +165,8 @@ class ServiceProcessor( } resolver.getClassDeclarationByName("dev.restate.sdk.springboot.RestateVirtualObject")?.let { metaAnnotationsToProcess.add( - MetaRestateAnnotation(it.qualifiedName!!, ServiceType.VIRTUAL_OBJECT)) + MetaRestateAnnotation(it.qualifiedName!!, ServiceType.VIRTUAL_OBJECT) + ) } resolver.getClassDeclarationByName("dev.restate.sdk.springboot.RestateWorkflow")?.let { metaAnnotationsToProcess.add(MetaRestateAnnotation(it.qualifiedName!!, ServiceType.WORKFLOW)) @@ -175,8 +188,10 @@ class ServiceProcessor( when (annotatedElement.classKind) { ClassKind.INTERFACE, ClassKind.CLASS -> { - if (annotatedElement.containingFile!!.origin != Origin.KOTLIN || - options.isClassDisabled(annotatedElement.qualifiedName!!.asString())) { + if ( + annotatedElement.containingFile!!.origin != Origin.KOTLIN || + options.isClassDisabled(annotatedElement.qualifiedName!!.asString()) + ) { // Skip if it's not kotlin continue } @@ -184,12 +199,14 @@ class ServiceProcessor( } ClassKind.ANNOTATION_CLASS -> { metaAnnotationsToProcess.add( - MetaRestateAnnotation(annotatedElement.qualifiedName!!, metaAnnotation.serviceType)) + MetaRestateAnnotation(annotatedElement.qualifiedName!!, metaAnnotation.serviceType) + ) } else -> logger.error( "The ServiceProcessor supports only interfaces or classes declarations", - annotatedElement) + annotatedElement, + ) } } metaAnnotation = metaAnnotationsToProcess.removeFirstOrNull() diff --git a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessorProvider.kt b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessorProvider.kt index a4927267..efa7fe7e 100644 --- a/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessorProvider.kt +++ b/sdk-api-kotlin-gen/src/main/kotlin/dev/restate/sdk/kotlin/gen/ServiceProcessorProvider.kt @@ -19,6 +19,7 @@ class ServiceProcessorProvider : SymbolProcessorProvider { return ServiceProcessor( logger = environment.logger, codeGenerator = environment.codeGenerator, - options = AnnotationProcessingOptions(environment.options)) + options = AnnotationProcessingOptions(environment.options), + ) } } diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt index 601540ec..f5b91182 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/ContextImpl.kt @@ -29,7 +29,7 @@ import kotlinx.coroutines.future.await internal class ContextImpl internal constructor( internal val handlerContext: HandlerContext, - internal val contextSerdeFactory: SerdeFactory + internal val contextSerdeFactory: SerdeFactory, ) : WorkflowContext { override fun key(): String { return this.handlerContext.objectKey() @@ -76,7 +76,8 @@ internal constructor( request.getTarget(), resolveAndSerialize(request.getRequestTypeTag(), request.getRequest()), request.getIdempotencyKey(), - request.getHeaders()?.entries) + request.getHeaders()?.entries, + ) .await() val callAsyncResult = @@ -89,7 +90,7 @@ internal constructor( override suspend fun send( request: Request, - delay: Duration? + delay: Duration?, ): InvocationHandle = resolveSerde(request.getResponseTypeTag()).let { responseSerde -> val invocationIdAsyncResult = @@ -99,7 +100,8 @@ internal constructor( resolveAndSerialize(request.getRequestTypeTag(), request.getRequest()), request.getIdempotencyKey(), request.getHeaders()?.entries, - delay?.toJavaDuration()) + delay?.toJavaDuration(), + ) .await() object : BaseInvocationHandle(handlerContext, responseSerde) { @@ -109,7 +111,7 @@ internal constructor( override fun invocationHandle( invocationId: String, - responseTypeTag: TypeTag + responseTypeTag: TypeTag, ): InvocationHandle = resolveSerde(responseTypeTag).let { responseSerde -> object : BaseInvocationHandle(handlerContext, responseSerde) { @@ -121,14 +123,16 @@ internal constructor( typeTag: TypeTag, name: String, retryPolicy: RetryPolicy?, - block: suspend () -> T + block: suspend () -> T, ): DurableFuture { val serde: Serde = resolveSerde(typeTag) val coroutineCtx = currentCoroutineContext() val javaRetryPolicy = retryPolicy?.let { dev.restate.sdk.common.RetryPolicy.exponential( - it.initialDelay.toJavaDuration(), it.exponentiationFactor) + it.initialDelay.toJavaDuration(), + it.exponentiationFactor, + ) .setMaxAttempts(it.maxAttempts) .setMaxDelay(it.maxDelay?.toJavaDuration()) .setMaxDuration(it.maxDuration?.toJavaDuration()) @@ -199,14 +203,18 @@ internal constructor( SingleDurableFutureImpl( handlerContext .resolvePromise( - key.name(), serde.serializeWrappingException(handlerContext, payload)) - .await()) + key.name(), + serde.serializeWrappingException(handlerContext, payload), + ) + .await() + ) .await() } override suspend fun reject(reason: String) { SingleDurableFutureImpl( - handlerContext.rejectPromise(key.name(), TerminalException(reason)).await()) + handlerContext.rejectPromise(key.name(), TerminalException(reason)).await() + ) .await() } } diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/HandlerRunner.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/HandlerRunner.kt index b70f0112..75f1ac56 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/HandlerRunner.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/HandlerRunner.kt @@ -28,7 +28,7 @@ class HandlerRunner internal constructor( private val runner: suspend (CTX, REQ) -> RES, private val contextSerdeFactory: SerdeFactory, - private val options: Options + private val options: Options, ) : dev.restate.sdk.endpoint.definition.HandlerRunner { companion object { @@ -73,7 +73,8 @@ internal constructor( Unit }, contextSerdeFactory, - options) + options, + ) } /** @@ -91,7 +92,8 @@ internal constructor( Unit }, contextSerdeFactory, - options) + options, + ) } } @@ -99,7 +101,7 @@ internal constructor( handlerContext: HandlerContext, requestSerde: Serde, responseSerde: Serde, - onClosedInvocationStreamHook: AtomicReference + onClosedInvocationStreamHook: AtomicReference, ): CompletableFuture { val ctx: Context = ContextImpl(handlerContext, contextSerdeFactory) @@ -108,7 +110,8 @@ internal constructor( options.coroutineContext + dev.restate.sdk.endpoint.definition.HandlerRunner.HANDLER_CONTEXT_THREAD_LOCAL .asContextElement(handlerContext) + - handlerContext.request().openTelemetryContext()!!.asContextElement()) + handlerContext.request().openTelemetryContext()!!.asContextElement() + ) val completableFuture = CompletableFuture() val job = @@ -125,7 +128,9 @@ internal constructor( completableFuture.completeExceptionally( throw TerminalException( TerminalException.BAD_REQUEST_CODE, - "Cannot deserialize request: " + e.message)) + "Cannot deserialize request: " + e.message, + ) + ) return@launch } diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/KtSerdes.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/KtSerdes.kt index 8e12cc7e..da50d146 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/KtSerdes.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/KtSerdes.kt @@ -47,7 +47,8 @@ object KtDurablePromiseKey { /** Creates a json [StateKey]. */ @Deprecated( "Use durablePromiseKey() instead", - replaceWith = ReplaceWith(expression = "durablePromiseKey()")) + replaceWith = ReplaceWith(expression = "durablePromiseKey()"), + ) inline fun json(name: String): DurablePromiseKey { return DurablePromiseKey.of(name, KtSerdes.json()) } @@ -87,7 +88,8 @@ object KtSerdes { override fun serialize(value: T?): Slice { if (value == null) { return Slice.wrap( - Json.encodeToString(JsonNull.serializer(), JsonNull).encodeToByteArray()) + Json.encodeToString(JsonNull.serializer(), JsonNull).encodeToByteArray() + ) } return Slice.wrap(Json.encodeToString(serializer, value).encodeToByteArray()) @@ -95,7 +97,9 @@ object KtSerdes { override fun deserialize(value: Slice): T { return Json.decodeFromString( - serializer, String(value.toByteArray(), StandardCharsets.UTF_8)) + serializer, + String(value.toByteArray(), StandardCharsets.UTF_8), + ) } override fun contentType(): String { diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/RetryPolicy.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/RetryPolicy.kt index 79bd8a28..b720ac8c 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/RetryPolicy.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/RetryPolicy.kt @@ -42,7 +42,7 @@ data class RetryPolicy( * the nature of the `run` operation, which executes the closure on the service and sends the * result afterward to Restate. */ - val maxDuration: Duration? = null + val maxDuration: Duration? = null, ) { data class Builder( @@ -50,7 +50,7 @@ data class RetryPolicy( var exponentiationFactor: Float = 2.0f, var maxDelay: Duration? = null, var maxAttempts: Int? = null, - var maxDuration: Duration? = null + var maxDuration: Duration? = null, ) { fun build() = RetryPolicy( @@ -58,7 +58,8 @@ data class RetryPolicy( exponentiationFactor = exponentiationFactor, maxDelay = maxDelay, maxDuration = maxDuration, - maxAttempts = maxAttempts) + maxAttempts = maxAttempts, + ) } } diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/Util.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/Util.kt index eee82127..b8341d69 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/Util.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/Util.kt @@ -15,7 +15,7 @@ import kotlinx.coroutines.CancellationException internal fun Serde.serializeWrappingException( handlerContext: HandlerContext, - value: T? + value: T?, ): Slice { return try { this.serialize(value) diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt index e47739bd..78fbc731 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/api.kt @@ -75,7 +75,7 @@ sealed interface Context { */ suspend fun send( request: Request, - delay: Duration? = null + delay: Duration? = null, ): InvocationHandle /** @@ -87,7 +87,7 @@ sealed interface Context { */ fun invocationHandle( invocationId: String, - responseTypeTag: TypeTag + responseTypeTag: TypeTag, ): InvocationHandle /** @@ -140,7 +140,7 @@ sealed interface Context { typeTag: TypeTag, name: String = "", retryPolicy: RetryPolicy? = null, - block: suspend () -> T + block: suspend () -> T, ): T { return runAsync(typeTag, name, retryPolicy, block).await() } @@ -165,7 +165,7 @@ sealed interface Context { typeTag: TypeTag, name: String = "", retryPolicy: RetryPolicy? = null, - block: suspend () -> T + block: suspend () -> T, ): DurableFuture /** @@ -265,7 +265,7 @@ inline fun Context.invocationHandle( suspend inline fun Context.runBlock( name: String = "", retryPolicy: RetryPolicy? = null, - noinline block: suspend () -> T + noinline block: suspend () -> T, ): T { return this.runBlock(typeTag(), name, retryPolicy, block) } @@ -289,7 +289,7 @@ suspend inline fun Context.runBlock( suspend inline fun Context.runAsync( name: String = "", retryPolicy: RetryPolicy? = null, - noinline block: suspend () -> T + noinline block: suspend () -> T, ): DurableFuture { return this.runAsync(typeTag(), name, retryPolicy, block) } @@ -482,7 +482,7 @@ sealed interface DurableFuture { */ suspend fun map( transformSuccess: suspend (value: T) -> R, - transformFailure: suspend (exception: TerminalException) -> R + transformFailure: suspend (exception: TerminalException) -> R, ): DurableFuture /** @@ -500,7 +500,7 @@ sealed interface DurableFuture { fun all( first: DurableFuture<*>, second: DurableFuture<*>, - vararg others: DurableFuture<*> + vararg others: DurableFuture<*>, ): DurableFuture { return wrapAllDurableFuture(listOf(first) + listOf(second) + others.asList()) } @@ -514,7 +514,7 @@ sealed interface DurableFuture { fun any( first: DurableFuture<*>, second: DurableFuture<*>, - vararg others: DurableFuture<*> + vararg others: DurableFuture<*>, ): DurableFuture { return wrapAnyDurableFuture(listOf(first) + listOf(second) + others.asList()) } @@ -673,7 +673,8 @@ sealed interface DurablePromise { @Deprecated( message = "Use future() instead", level = DeprecationLevel.WARNING, - replaceWith = ReplaceWith(expression = "future()")) + replaceWith = ReplaceWith(expression = "future()"), + ) suspend fun awaitable(): DurableFuture { return future() } @@ -715,7 +716,7 @@ suspend fun Request.call( /** Shorthand for [Context.send] */ suspend fun Request.send( context: Context, - delay: Duration? = null + delay: Duration? = null, ): InvocationHandle { return context.send(this, delay) } diff --git a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/futures.kt b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/futures.kt index 12b9fbb5..917f930c 100644 --- a/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/futures.kt +++ b/sdk-api-kotlin/src/main/kotlin/dev/restate/sdk/kotlin/futures.kt @@ -43,8 +43,9 @@ internal abstract class BaseDurableFutureImpl : DurableFuture { return (DurableFuture.any( this, SingleDurableFutureImpl( - asyncResult().ctx().timer(duration.toJavaDuration(), null).await())) - as BaseDurableFutureImpl<*>) + asyncResult().ctx().timer(duration.toJavaDuration(), null).await() + ), + ) as BaseDurableFutureImpl<*>) .simpleMap { if (it == 1) { throw TimeoutException("Timed out waiting for durable future after $duration") @@ -61,7 +62,8 @@ internal abstract class BaseDurableFutureImpl : DurableFuture { fun simpleMap(transform: (T) -> R): DurableFuture { return SingleDurableFutureImpl( - this.asyncResult().map { CompletableFuture.completedFuture(transform(it)) }) + this.asyncResult().map { CompletableFuture.completedFuture(transform(it)) } + ) } override suspend fun map(transform: suspend (T) -> R): DurableFuture { @@ -80,12 +82,13 @@ internal abstract class BaseDurableFutureImpl : DurableFuture { completableFuture.complete(r) } completableFuture - }) + } + ) } override suspend fun map( transformSuccess: suspend (T) -> R, - transformFailure: suspend (TerminalException) -> R + transformFailure: suspend (TerminalException) -> R, ): DurableFuture { var ctx = currentCoroutineContext() return SingleDurableFutureImpl( @@ -118,7 +121,9 @@ internal abstract class BaseDurableFutureImpl : DurableFuture { completableFuture.complete(r) } completableFuture - })) + }, + ) + ) } override suspend fun mapFailure(transform: suspend (TerminalException) -> T): DurableFuture { @@ -137,7 +142,8 @@ internal abstract class BaseDurableFutureImpl : DurableFuture { completableFuture.complete(newT) } completableFuture - }) + } + ) } } @@ -153,7 +159,9 @@ internal fun wrapAllDurableFuture(durableFutures: List>): Durab val ctx = (durableFutures.get(0) as BaseDurableFutureImpl<*>).asyncResult().ctx() return SingleDurableFutureImpl( ctx.createAllAsyncResult( - durableFutures.map { (it as BaseDurableFutureImpl<*>).asyncResult() })) + durableFutures.map { (it as BaseDurableFutureImpl<*>).asyncResult() } + ) + ) .simpleMap {} } @@ -164,13 +172,15 @@ internal fun wrapAnyDurableFuture( val ctx = (durableFutures.get(0) as BaseDurableFutureImpl<*>).asyncResult().ctx() return SingleDurableFutureImpl( ctx.createAnyAsyncResult( - durableFutures.map { (it as BaseDurableFutureImpl<*>).asyncResult() })) + durableFutures.map { (it as BaseDurableFutureImpl<*>).asyncResult() } + ) + ) } internal class CallDurableFutureImpl internal constructor( callAsyncResult: AsyncResult, - private val invocationIdAsyncResult: AsyncResult + private val invocationIdAsyncResult: AsyncResult, ) : SingleDurableFutureImpl(callAsyncResult), CallDurableFuture { override suspend fun invocationId(): String { return invocationIdAsyncResult.poll().await() @@ -180,7 +190,7 @@ internal constructor( internal abstract class BaseInvocationHandle internal constructor( private val handlerContext: HandlerContext, - private val responseSerde: Serde + private val responseSerde: Serde, ) : InvocationHandle { override suspend fun cancel() { val ignored = handlerContext.cancelInvocation(invocationId()).await() @@ -190,7 +200,8 @@ internal constructor( SingleDurableFutureImpl( handlerContext.attachInvocation(invocationId()).await().map { CompletableFuture.completedFuture(responseSerde.deserialize(it)) - }) + } + ) override suspend fun output(): Output = SingleDurableFutureImpl(handlerContext.getInvocationOutput(invocationId()).await()) @@ -201,7 +212,8 @@ internal constructor( internal class AwakeableImpl internal constructor(asyncResult: AsyncResult, serde: Serde, override val id: String) : SingleDurableFutureImpl( - asyncResult.map { CompletableFuture.completedFuture(serde.deserialize(it)) }), + asyncResult.map { CompletableFuture.completedFuture(serde.deserialize(it)) } + ), Awakeable internal class AwakeableHandleImpl(val contextImpl: ContextImpl, val id: String) : AwakeableHandle { diff --git a/sdk-common/build.gradle.kts b/sdk-common/build.gradle.kts index ab7516c4..c3a2d45f 100644 --- a/sdk-common/build.gradle.kts +++ b/sdk-common/build.gradle.kts @@ -35,7 +35,7 @@ sourceSets { main { java { srcDir(generatedVersionDir) } } } fun String.runCommand( workingDir: File = File("."), timeoutAmount: Long = 5, - timeoutUnit: TimeUnit = TimeUnit.SECONDS + timeoutUnit: TimeUnit = TimeUnit.SECONDS, ): String = ProcessBuilder(split("\\s(?=(?:[^'\"`]*(['\"`])[^'\"`]*\\1)*[^'\"`]*$)".toRegex())) .directory(workingDir) @@ -74,7 +74,8 @@ val generateVersionClass = public static final String X_RESTATE_SERVER = "restate-sdk-java/" + VERSION + "_" + GIT_HASH; } """ - .trimIndent()) + .trimIndent() + ) check(file("${projectDir}/build/version/dev/restate/sdk/version/Version.java").exists()) { "${projectDir}/build/version/dev/restate/sdk/version/Version.java doesn't exist?!" diff --git a/sdk-core/build.gradle.kts b/sdk-core/build.gradle.kts index 07a98f3f..7a42dd7f 100644 --- a/sdk-core/build.gradle.kts +++ b/sdk-core/build.gradle.kts @@ -68,6 +68,7 @@ dependencies { testImplementation(libs.kotlinx.serialization.core) testImplementation(libs.vertx.junit5) testImplementation(libs.vertx.kotlin.coroutines) + testRuntimeOnly(libs.junit.platform.launcher) } // Configure source sets for protobuf plugin and jsonschema2pojo @@ -115,13 +116,15 @@ tasks { "dev.restate.sdk.core.javaapi.reflections.ObjectGreeterImplementedFromInterface", "dev.restate.sdk.core.javaapi.reflections.PrimitiveTypes", "dev.restate.sdk.core.javaapi.reflections.RawInputOutput", - "dev.restate.sdk.core.javaapi.reflections.ServiceGreeter") + "dev.restate.sdk.core.javaapi.reflections.ServiceGreeter", + ) options.compilerArgs.addAll( listOf( "-parameters", "-Adev.restate.codegen.disabledClasses=${disabledClassesCodegen.joinToString(",")}", - )) + ) + ) } withType().configureEach { dependsOn(generateJsonSchema2Pojo, generateProto) } withType().configureEach { @@ -156,7 +159,8 @@ configure { // their repos. targetExclude( fileTree("$rootDir/sdk-common/src/main/proto") { include("**/*.*") }, - fileTree("$rootDir/sdk-core/src/main/service-protocol") { include("**/*.*") }) + fileTree("$rootDir/sdk-core/src/main/service-protocol") { include("**/*.*") }, + ) licenseHeaderFile("$rootDir/config/license-header", "syntax") } diff --git a/sdk-core/src/main/java/dev/restate/sdk/core/statemachine/MessageType.java b/sdk-core/src/main/java/dev/restate/sdk/core/statemachine/MessageType.java index fdfea066..b4dd6e10 100644 --- a/sdk-core/src/main/java/dev/restate/sdk/core/statemachine/MessageType.java +++ b/sdk-core/src/main/java/dev/restate/sdk/core/statemachine/MessageType.java @@ -119,17 +119,17 @@ public Parser messageParser() { case GetInvocationOutputCommandMessage -> Protocol.GetInvocationOutputCommandMessage.parser(); case CompleteAwakeableCommandMessage -> Protocol.CompleteAwakeableCommandMessage.parser(); case GetLazyStateCompletionNotificationMessage, - SignalNotificationMessage, - GetLazyStateKeysCompletionNotificationMessage, - GetPromiseCompletionNotificationMessage, - PeekPromiseCompletionNotificationMessage, - CompletePromiseCompletionNotificationMessage, - SleepCompletionNotificationMessage, - CallInvocationIdCompletionNotificationMessage, - CallCompletionNotificationMessage, - RunCompletionNotificationMessage, - AttachInvocationCompletionNotificationMessage, - GetInvocationOutputCompletionNotificationMessage -> + SignalNotificationMessage, + GetLazyStateKeysCompletionNotificationMessage, + GetPromiseCompletionNotificationMessage, + PeekPromiseCompletionNotificationMessage, + CompletePromiseCompletionNotificationMessage, + SleepCompletionNotificationMessage, + CallInvocationIdCompletionNotificationMessage, + CallCompletionNotificationMessage, + RunCompletionNotificationMessage, + AttachInvocationCompletionNotificationMessage, + GetInvocationOutputCompletionNotificationMessage -> Protocol.NotificationTemplate.parser(); }; } @@ -186,25 +186,25 @@ public short encode() { public boolean isCommand() { return switch (this) { case InputCommandMessage, - GetLazyStateCommandMessage, - OutputCommandMessage, - SetStateCommandMessage, - ClearStateCommandMessage, - ClearAllStateCommandMessage, - GetLazyStateKeysCommandMessage, - GetEagerStateCommandMessage, - GetEagerStateKeysCommandMessage, - GetPromiseCommandMessage, - PeekPromiseCommandMessage, - CompletePromiseCommandMessage, - SleepCommandMessage, - CallCommandMessage, - OneWayCallCommandMessage, - SendSignalCommandMessage, - RunCommandMessage, - AttachInvocationCommandMessage, - GetInvocationOutputCommandMessage, - CompleteAwakeableCommandMessage -> + GetLazyStateCommandMessage, + OutputCommandMessage, + SetStateCommandMessage, + ClearStateCommandMessage, + ClearAllStateCommandMessage, + GetLazyStateKeysCommandMessage, + GetEagerStateCommandMessage, + GetEagerStateKeysCommandMessage, + GetPromiseCommandMessage, + PeekPromiseCommandMessage, + CompletePromiseCommandMessage, + SleepCommandMessage, + CallCommandMessage, + OneWayCallCommandMessage, + SendSignalCommandMessage, + RunCommandMessage, + AttachInvocationCommandMessage, + GetInvocationOutputCommandMessage, + CompleteAwakeableCommandMessage -> true; default -> false; }; @@ -213,17 +213,17 @@ public boolean isCommand() { public boolean isNotification() { return switch (this) { case GetLazyStateCompletionNotificationMessage, - SignalNotificationMessage, - GetLazyStateKeysCompletionNotificationMessage, - GetPromiseCompletionNotificationMessage, - PeekPromiseCompletionNotificationMessage, - CompletePromiseCompletionNotificationMessage, - SleepCompletionNotificationMessage, - CallInvocationIdCompletionNotificationMessage, - CallCompletionNotificationMessage, - RunCompletionNotificationMessage, - AttachInvocationCompletionNotificationMessage, - GetInvocationOutputCompletionNotificationMessage -> + SignalNotificationMessage, + GetLazyStateKeysCompletionNotificationMessage, + GetPromiseCompletionNotificationMessage, + PeekPromiseCompletionNotificationMessage, + CompletePromiseCompletionNotificationMessage, + SleepCompletionNotificationMessage, + CallInvocationIdCompletionNotificationMessage, + CallCompletionNotificationMessage, + RunCompletionNotificationMessage, + AttachInvocationCompletionNotificationMessage, + GetInvocationOutputCompletionNotificationMessage -> true; default -> false; }; diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CallTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CallTest.kt index 6a4251d0..9b21532c 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CallTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CallTest.kt @@ -21,14 +21,15 @@ class CallTest : CallTestSuite() { target: Target, idempotencyKey: String, headers: Map, - body: Slice + body: Slice, ) = testDefinitionForService("OneWayCall") { ctx, _: Unit -> val ignored = ctx.send( Request.of(target, Serde.SLICE, Serde.RAW, body) .headers(headers) - .idempotencyKey(idempotencyKey)) + .idempotencyKey(idempotencyKey) + ) } override fun implicitCancellation(target: Target, body: Slice) = diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenDiscoveryTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenDiscoveryTest.kt index 57138ef6..b2783f59 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenDiscoveryTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenDiscoveryTest.kt @@ -57,7 +57,8 @@ class CodegenDiscoveryTest { override fun greet(context: dev.restate.sdk.kotlin.Context, request: String): String { TODO("Not yet implemented") } - }) + } + ) .extractingService("MyExplicitName") .extractingHandler("my_greeter") Assertions.assertThat(GreeterWithExplicitNameHandlers.Metadata.SERVICE_NAME) @@ -83,7 +84,8 @@ class CodegenDiscoveryTest { it.documentation = "My handler documentation" } } - }) + } + ) .extractingService("RawInputOutput") .returns("My service documentation", Service::getDocumentation) .extractingHandler("rawInputWithCustomCt") diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenTest.kt index dca4a933..9ee50f07 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/CodegenTest.kt @@ -62,7 +62,7 @@ class CodegenTest : TestDefinitions.TestSuite { @Exclusive suspend fun complexType( context: ObjectContext, - request: Map> + request: Map>, ): Map> { return mapOf() } @@ -190,7 +190,7 @@ class CodegenTest : TestDefinitions.TestSuite { @Handler suspend fun rawInputWithCustomCt( context: Context, - @Raw(contentType = "application/vnd.my.custom") input: ByteArray + @Raw(contentType = "application/vnd.my.custom") input: ByteArray, ) { val client: CodegenTestRawInputOutputClient.ContextClient = CodegenTestRawInputOutputClient.fromContext(context) @@ -200,7 +200,7 @@ class CodegenTest : TestDefinitions.TestSuite { @Handler suspend fun rawInputWithCustomAccept( context: Context, - @Accept("application/*") @Raw(contentType = "application/vnd.my.custom") input: ByteArray + @Accept("application/*") @Raw(contentType = "application/vnd.my.custom") input: ByteArray, ) { val client: CodegenTestRawInputOutputClient.ContextClient = CodegenTestRawInputOutputClient.fromContext(context) @@ -269,11 +269,13 @@ class CodegenTest : TestDefinitions.TestSuite { testInvocation({ NestedDataClass() }, "greet") .withInput( startMessage(1, "slinkydeveloper"), - inputCmd(jsonSerde(), NestedDataClass.Input("123"))) + inputCmd(jsonSerde(), NestedDataClass.Input("123")), + ) .onlyBidiStream() .expectingOutput( outputCmd(jsonSerde(), NestedDataClass.Output("123")), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ ObjectGreeterImplementedFromInterface() }, "greet") .withInput(startMessage(1, "slinkydeveloper"), inputCmd("Francesco")) .onlyBidiStream() @@ -284,7 +286,8 @@ class CodegenTest : TestDefinitions.TestSuite { .expectingOutput( callCmd(1, 2, Target.service("Empty", "emptyInput")), outputCmd("Till"), - END_MESSAGE) + END_MESSAGE, + ) .named("empty output"), testInvocation({ Empty() }, "emptyOutput") .withInput(startMessage(1), inputCmd("Francesco"), callCompletion(2, Serde.VOID, null)) @@ -292,7 +295,8 @@ class CodegenTest : TestDefinitions.TestSuite { .expectingOutput( callCmd(1, 2, Target.service("Empty", "emptyOutput"), "Francesco"), outputCmd(), - END_MESSAGE) + END_MESSAGE, + ) .named("empty output"), testInvocation({ Empty() }, "emptyInputOutput") .withInput(startMessage(1), inputCmd("Francesco"), callCompletion(2, Serde.VOID, null)) @@ -300,53 +304,74 @@ class CodegenTest : TestDefinitions.TestSuite { .expectingOutput( callCmd(1, 2, Target.service("Empty", "emptyInputOutput")), outputCmd(), - END_MESSAGE) + END_MESSAGE, + ) .named("empty input and empty output"), testInvocation({ PrimitiveTypes() }, "primitiveOutput") .withInput(startMessage(1), inputCmd(), callCompletion(2, TestSerdes.INT, 10)) .onlyBidiStream() .expectingOutput( callCmd( - 1, 2, Target.service("PrimitiveTypes", "primitiveOutput"), Serde.VOID, null), + 1, + 2, + Target.service("PrimitiveTypes", "primitiveOutput"), + Serde.VOID, + null, + ), outputCmd(TestSerdes.INT, 10), - END_MESSAGE) + END_MESSAGE, + ) .named("primitive output"), testInvocation({ PrimitiveTypes() }, "primitiveInput") .withInput(startMessage(1), inputCmd(10), callCompletion(2, Serde.VOID, null)) .onlyBidiStream() .expectingOutput( callCmd( - 1, 2, Target.service("PrimitiveTypes", "primitiveInput"), TestSerdes.INT, 10), + 1, + 2, + Target.service("PrimitiveTypes", "primitiveInput"), + TestSerdes.INT, + 10, + ), outputCmd(), - END_MESSAGE) + END_MESSAGE, + ) .named("primitive input"), testInvocation({ RawInputOutput() }, "rawInput") .withInput( startMessage(1), inputCmd("{{".toByteArray()), - callCompletion(2, KotlinSerializationSerdeFactory.UNIT, Unit)) + callCompletion(2, KotlinSerializationSerdeFactory.UNIT, Unit), + ) .onlyBidiStream() .expectingOutput( callCmd(1, 2, Target.service("RawInputOutput", "rawInput"), "{{".toByteArray()), outputCmd(), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ RawInputOutput() }, "rawInputWithCustomCt") .withInput( startMessage(1), inputCmd("{{".toByteArray()), - callCompletion(2, KotlinSerializationSerdeFactory.UNIT, Unit)) + callCompletion(2, KotlinSerializationSerdeFactory.UNIT, Unit), + ) .onlyBidiStream() .expectingOutput( callCmd( 1, 2, Target.service("RawInputOutput", "rawInputWithCustomCt"), - "{{".toByteArray()), + "{{".toByteArray(), + ), outputCmd(), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ RawInputOutput() }, "rawOutput") .withInput( - startMessage(1), inputCmd(), callCompletion(2, Serde.RAW, "{{".toByteArray())) + startMessage(1), + inputCmd(), + callCompletion(2, Serde.RAW, "{{".toByteArray()), + ) .onlyBidiStream() .expectingOutput( callCmd( @@ -354,12 +379,17 @@ class CodegenTest : TestDefinitions.TestSuite { 2, Target.service("RawInputOutput", "rawOutput"), KotlinSerializationSerdeFactory.UNIT, - Unit), + Unit, + ), outputCmd("{{".toByteArray()), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ RawInputOutput() }, "rawOutputWithCustomCT") .withInput( - startMessage(1), inputCmd(), callCompletion(2, Serde.RAW, "{{".toByteArray())) + startMessage(1), + inputCmd(), + callCompletion(2, Serde.RAW, "{{".toByteArray()), + ) .onlyBidiStream() .expectingOutput( callCmd( @@ -367,14 +397,17 @@ class CodegenTest : TestDefinitions.TestSuite { 2, Target.service("RawInputOutput", "rawOutputWithCustomCT"), KotlinSerializationSerdeFactory.UNIT, - Unit), + Unit, + ), outputCmd("{{".toByteArray()), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ CornerCases() }, "returnNull") .withInput( startMessage(1, "mykey"), inputCmd(jsonSerde(), null), - callCompletion(2, jsonSerde(), null)) + callCompletion(2, jsonSerde(), null), + ) .onlyBidiStream() .expectingOutput( callCmd( @@ -382,9 +415,11 @@ class CodegenTest : TestDefinitions.TestSuite { 2, Target.virtualObject("CodegenTestCornerCases", "mykey", "returnNull"), jsonSerde(), - null), + null, + ), outputCmd(jsonSerde(), null), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ CornerCases() }, "badReturnTypeInferred") .withInput(startMessage(1, "mykey"), inputCmd()) .onlyBidiStream() @@ -392,12 +427,17 @@ class CodegenTest : TestDefinitions.TestSuite { oneWayCallCmd( 1, Target.virtualObject( - "CodegenTestCornerCases", "mykey", "badReturnTypeInferred"), + "CodegenTestCornerCases", + "mykey", + "badReturnTypeInferred", + ), null, null, - Slice.EMPTY), + Slice.EMPTY, + ), outputCmd(), - END_MESSAGE), + END_MESSAGE, + ), testInvocation({ CustomSerdeService() }, "echo") .withInput(startMessage(1), inputCmd(byteArrayOf(1))) .onlyBidiStream() diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/KotlinAPITests.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/KotlinAPITests.kt index 601dba9c..ea132e9d 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/KotlinAPITests.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/KotlinAPITests.kt @@ -42,13 +42,14 @@ class KotlinAPITests : TestRunner() { StateMachineFailuresTest(), UserFailuresTest(), RandomTest(), - CodegenTest()) + CodegenTest(), + ) } companion object { inline fun testDefinitionForService( name: String, - noinline runner: suspend (Context, REQ) -> RES + noinline runner: suspend (Context, REQ) -> RES, ): TestInvocationBuilder { return TestDefinitions.testInvocation( ServiceDefinition.of( @@ -63,13 +64,18 @@ class KotlinAPITests : TestRunner() { HandlerRunner.of( KotlinSerializationSerdeFactory(), HandlerRunner.Options(Dispatchers.Unconfined), - runner)))), - "run") + runner, + ), + ) + ), + ), + "run", + ) } inline fun testDefinitionForVirtualObject( name: String, - noinline runner: suspend (ObjectContext, REQ) -> RES + noinline runner: suspend (ObjectContext, REQ) -> RES, ): TestInvocationBuilder { return TestDefinitions.testInvocation( ServiceDefinition.of( @@ -84,13 +90,18 @@ class KotlinAPITests : TestRunner() { HandlerRunner.of( KotlinSerializationSerdeFactory(), HandlerRunner.Options(Dispatchers.Unconfined), - runner)))), - "run") + runner, + ), + ) + ), + ), + "run", + ) } inline fun testDefinitionForWorkflow( name: String, - noinline runner: suspend (WorkflowContext, REQ) -> RES + noinline runner: suspend (WorkflowContext, REQ) -> RES, ): TestInvocationBuilder { return TestDefinitions.testInvocation( ServiceDefinition.of( @@ -105,14 +116,24 @@ class KotlinAPITests : TestRunner() { HandlerRunner.of( KotlinSerializationSerdeFactory(), HandlerRunner.Options(Dispatchers.Unconfined), - runner)))), - "run") + runner, + ), + ) + ), + ), + "run", + ) } suspend fun callGreeterGreetService(ctx: Context, parameter: String): DurableFuture { return ctx.call( Request.of( - ProtoUtils.GREETER_SERVICE_TARGET, TestSerdes.STRING, TestSerdes.STRING, parameter)) + ProtoUtils.GREETER_SERVICE_TARGET, + TestSerdes.STRING, + TestSerdes.STRING, + parameter, + ) + ) } } } diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/PromiseTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/PromiseTest.kt index 918c0c1b..4b998966 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/PromiseTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/PromiseTest.kt @@ -22,7 +22,7 @@ class PromiseTest : PromiseTestSuite() { override fun awaitPeekPromise( promiseKey: String, - emptyCaseReturnValue: String + emptyCaseReturnValue: String, ): TestDefinitions.TestInvocationBuilder = testDefinitionForWorkflow("AwaitPeekPromise") { ctx, _: Unit -> ctx.promise(durablePromiseKey(promiseKey)).peek().orElse(emptyCaseReturnValue) @@ -35,7 +35,7 @@ class PromiseTest : PromiseTestSuite() { override fun awaitResolvePromise( promiseKey: String, - completionValue: String + completionValue: String, ): TestDefinitions.TestInvocationBuilder = testDefinitionForWorkflow("ResolvePromise") { ctx, _: Unit -> try { @@ -48,7 +48,7 @@ class PromiseTest : PromiseTestSuite() { override fun awaitRejectPromise( promiseKey: String, - rejectReason: String + rejectReason: String, ): TestDefinitions.TestInvocationBuilder = testDefinitionForWorkflow("RejectPromise") { ctx, _: Unit -> try { diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/SideEffectTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/SideEffectTest.kt index be1ee012..f593da98 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/SideEffectTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/SideEffectTest.kt @@ -64,17 +64,21 @@ class SideEffectTest : SideEffectTestSuite() { KotlinSerializationSerdeFactory(), HandlerRunner.Options( Dispatchers.Unconfined + - CoroutineName("CheckContextSwitchingTestCoroutine"))) { - ctx: Context, - _: Unit -> - val sideEffectCoroutine = - ctx.runBlock { coroutineContext[CoroutineName]!!.name } - check(sideEffectCoroutine == "CheckContextSwitchingTestCoroutine") { - "Side effect thread is not running within the same coroutine context of the handler method: $sideEffectCoroutine" - } - "Hello" - }))), - "run") + CoroutineName("CheckContextSwitchingTestCoroutine") + ), + ) { ctx: Context, _: Unit -> + val sideEffectCoroutine = + ctx.runBlock { coroutineContext[CoroutineName]!!.name } + check(sideEffectCoroutine == "CheckContextSwitchingTestCoroutine") { + "Side effect thread is not running within the same coroutine context of the handler method: $sideEffectCoroutine" + } + "Hello" + }, + ) + ), + ), + "run", + ) override fun failingSideEffect(name: String, reason: String) = testDefinitionForService("FailingSideEffect") { ctx, _: Unit -> @@ -85,7 +89,7 @@ class SideEffectTest : SideEffectTestSuite() { firstSideEffect: String, secondSideEffect: String, successValue: String, - failureReason: String + failureReason: String, ) = testDefinitionForService("AwaitAllSideEffectWithFirstFailing") { ctx, _: Unit -> val fut1 = @@ -98,7 +102,7 @@ class SideEffectTest : SideEffectTestSuite() { firstSideEffect: String, secondSideEffect: String, successValue: String, - failureReason: String + failureReason: String, ) = testDefinitionForService("AwaitAllSideEffectWithSecondFailing") { ctx, _: Unit -> val fut1 = ctx.runAsync(firstSideEffect) { successValue } @@ -117,9 +121,11 @@ class SideEffectTest : SideEffectTestSuite() { exponentiationFactor = it.exponentiationFactor, maxDelay = it.maxDelay?.toKotlinDuration(), maxDuration = it.maxDuration?.toKotlinDuration(), - maxAttempts = it.maxAttempts) - }) { - throw IllegalStateException(reason) - } + maxAttempts = it.maxAttempts, + ) + } + ) { + throw IllegalStateException(reason) + } } } diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateMachineFailuresTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateMachineFailuresTest.kt index 748b48bb..94c7da30 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateMachineFailuresTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateMachineFailuresTest.kt @@ -28,7 +28,8 @@ class StateMachineFailuresTest : StateMachineFailuresTestSuite() { Serde.using({ i: Int -> i.toString().toByteArray(StandardCharsets.UTF_8) }) { b: ByteArray? -> String(b!!, StandardCharsets.UTF_8).toInt() - }) + }, + ) } override fun getState(nonTerminalExceptionsSeen: AtomicInteger): TestInvocationBuilder = diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateTest.kt index 201a1112..4f63035f 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/kotlinapi/StateTest.kt @@ -64,19 +64,23 @@ class StateTest : StateTestSuite() { startMessage(3), inputCmd(), getEagerStateCmd("STATE", jsonSerde(), Data(1, "Till")), - setStateCmd("STATE", jsonSerde(), Data(2, "Till"))) + setStateCmd("STATE", jsonSerde(), Data(2, "Till")), + ) .expectingOutput(outputCmd("Hello " + Data(2, "Till")), END_MESSAGE) .named("With GetState and SetState"), getAndSetStateUsingKtSerdes() .withInput( startMessage(2), inputCmd(), - getEagerStateCmd("STATE", jsonSerde(), Data(1, "Till"))) + getEagerStateCmd("STATE", jsonSerde(), Data(1, "Till")), + ) .expectingOutput( setStateCmd("STATE", jsonSerde(), Data(2, "Till")), outputCmd("Hello " + Data(2, "Till")), - END_MESSAGE) + END_MESSAGE, + ) .named("With GetState already completed"), - )) + ), + ) } } diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTest.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTest.kt index 3d2870cf..497f5e95 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTest.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTest.kt @@ -75,7 +75,10 @@ internal class RestateHttpServerTest { ctx.sleep(1.seconds) "Hello $request. Count: $count" - }))) + }, + ) + ), + ) } @Test @@ -83,7 +86,10 @@ internal class RestateHttpServerTest { runBlocking(vertx.dispatcher()) { val endpointPort: Int = RestateHttpServer.fromEndpoint( - vertx, endpoint { bind(greeter()) }, HttpServerOptions().setPort(0)) + vertx, + endpoint { bind(greeter()) }, + HttpServerOptions().setPort(0), + ) .listen() .coAwait() .actualPort() @@ -96,7 +102,8 @@ internal class RestateHttpServerTest { HttpMethod.POST, endpointPort, "localhost", - "/invoke/$GREETER_NAME/unknownMethod") + "/invoke/$GREETER_NAME/unknownMethod", + ) .coAwait() // Prepare request header @@ -119,7 +126,10 @@ internal class RestateHttpServerTest { runBlocking(vertx.dispatcher()) { val endpointPort: Int = RestateHttpServer.fromEndpoint( - vertx, endpoint { bind(greeter()) }, HttpServerOptions().setPort(0)) + vertx, + endpoint { bind(greeter()) }, + HttpServerOptions().setPort(0), + ) .listen() .coAwait() .actualPort() diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTestExecutor.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTestExecutor.kt index 875856bb..5f2945bf 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTestExecutor.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTestExecutor.kt @@ -48,7 +48,10 @@ class RestateHttpServerTestExecutor(private val vertx: Vertx) : TestExecutor { // Start server val server = RestateHttpServer.fromEndpoint( - vertx, endpointBuilder.build(), HttpServerOptions().setPort(0)) + vertx, + endpointBuilder.build(), + HttpServerOptions().setPort(0), + ) server.listen().coAwait() val client = vertx.createHttpClient(RestateHttpServerTest.Companion.HTTP_CLIENT_OPTIONS) @@ -59,7 +62,8 @@ class RestateHttpServerTestExecutor(private val vertx: Vertx) : TestExecutor { HttpMethod.POST, server.actualPort(), "localhost", - "/invoke/${definition.serviceDefinition.serviceName}/${definition.method}") + "/invoke/${definition.serviceDefinition.serviceName}/${definition.method}", + ) .coAwait() // Prepare request header and send them @@ -67,18 +71,20 @@ class RestateHttpServerTestExecutor(private val vertx: Vertx) : TestExecutor { .setChunked(true) .putHeader( HttpHeaders.CONTENT_TYPE, - ProtoUtils.serviceProtocolContentTypeHeader(definition.isEnablePreviewContext)) + ProtoUtils.serviceProtocolContentTypeHeader(definition.isEnablePreviewContext), + ) .putHeader( HttpHeaders.ACCEPT, - ProtoUtils.serviceProtocolContentTypeHeader(definition.isEnablePreviewContext)) + ProtoUtils.serviceProtocolContentTypeHeader(definition.isEnablePreviewContext), + ) request.sendHead().coAwait() launch { for (msg in definition.input) { request .write( - Buffer.buffer( - Unpooled.wrappedBuffer(ProtoUtils.invocationInputToByteString(msg)))) + Buffer.buffer(Unpooled.wrappedBuffer(ProtoUtils.invocationInputToByteString(msg))) + ) .coAwait() yield() } @@ -98,7 +104,8 @@ class RestateHttpServerTestExecutor(private val vertx: Vertx) : TestExecutor { val buffers = inputChannel.receiveAsFlow().toList() definition.outputAssert.accept( - ProtoUtils.bufferToMessages(buffers.map { ByteBuffer.wrap(it.bytes) })) + ProtoUtils.bufferToMessages(buffers.map { ByteBuffer.wrap(it.bytes) }) + ) // Close the server server.close().coAwait() diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTests.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTests.kt index c030596c..97cda32a 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTests.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/RestateHttpServerTests.kt @@ -39,6 +39,7 @@ class RestateHttpServerTests : TestRunner() { override fun definitions(): Stream { return Stream.concat( Stream.concat(JavaAPITests().definitions(), KotlinAPITests().definitions()), - Stream.of(ThreadTrampoliningTestSuite())) + Stream.of(ThreadTrampoliningTestSuite()), + ) } } diff --git a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/ThreadTrampoliningTestSuite.kt b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/ThreadTrampoliningTestSuite.kt index 46a2a4bf..5a4f6eaf 100644 --- a/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/ThreadTrampoliningTestSuite.kt +++ b/sdk-core/src/test/kotlin/dev/restate/sdk/core/vertx/ThreadTrampoliningTestSuite.kt @@ -51,7 +51,7 @@ class ThreadTrampoliningTestSuite : TestDefinitions.TestSuite { private fun checkBlockingComponentTrampolineExecutor( ctx: dev.restate.sdk.Context, - _unused: Any? + _unused: Any?, ): Void? { val id = Thread.currentThread().id check(Vertx.currentContext() == null) @@ -76,16 +76,23 @@ class ThreadTrampoliningTestSuite : TestDefinitions.TestSuite { HandlerRunner.of( KotlinSerializationSerdeFactory(), HandlerRunner.Options( - Dispatchers.Default + nonBlockingCoroutineName)) { - ctx: Context, - _: Unit -> - checkNonBlockingComponentTrampolineExecutor(ctx) - }))), - "do") + Dispatchers.Default + nonBlockingCoroutineName + ), + ) { ctx: Context, _: Unit -> + checkNonBlockingComponentTrampolineExecutor(ctx) + }, + ) + ), + ), + "do", + ) .withInput(startMessage(1), inputCmd()) .onlyBidiStream() .expectingOutput( - runCmd(1), proposeRunCompletion(1, Serde.VOID, null), suspensionMessage(1)), + runCmd(1), + proposeRunCompletion(1, Serde.VOID, null), + suspensionMessage(1), + ), testInvocation( ServiceDefinition.of( "CheckBlockingComponentTrampolineExecutor", @@ -99,11 +106,20 @@ class ThreadTrampoliningTestSuite : TestDefinitions.TestSuite { dev.restate.sdk.HandlerRunner.of( this::checkBlockingComponentTrampolineExecutor, JacksonSerdeFactory(), - null)))), - "do") + null, + ), + ) + ), + ), + "do", + ) .withInput(startMessage(1), inputCmd()) .onlyBidiStream() .expectingOutput( - runCmd(1), proposeRunCompletion(1, Serde.VOID, null), suspensionMessage(1))) + runCmd(1), + proposeRunCompletion(1, Serde.VOID, null), + suspensionMessage(1), + ), + ) } } diff --git a/sdk-request-identity/build.gradle.kts b/sdk-request-identity/build.gradle.kts index d13eff9c..7aba9757 100644 --- a/sdk-request-identity/build.gradle.kts +++ b/sdk-request-identity/build.gradle.kts @@ -18,4 +18,5 @@ dependencies { testImplementation(libs.junit.jupiter) testImplementation(libs.assertj) + testRuntimeOnly(libs.junit.platform.launcher) } diff --git a/sdk-serde-jackson/build.gradle.kts b/sdk-serde-jackson/build.gradle.kts index 2e4e1df3..a27aaa6f 100644 --- a/sdk-serde-jackson/build.gradle.kts +++ b/sdk-serde-jackson/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { testImplementation(libs.junit.jupiter) testImplementation(libs.assertj) + testRuntimeOnly(libs.junit.platform.launcher) } tasks.withType { isFailOnError = false } diff --git a/sdk-serde-kotlinx/build.gradle.kts b/sdk-serde-kotlinx/build.gradle.kts index 7922b6c4..f23054f2 100644 --- a/sdk-serde-kotlinx/build.gradle.kts +++ b/sdk-serde-kotlinx/build.gradle.kts @@ -16,4 +16,5 @@ dependencies { testImplementation(libs.junit.jupiter) testImplementation(libs.assertj) + testRuntimeOnly(libs.junit.platform.launcher) } diff --git a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/DefaultJsonSchemaFactory.kt b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/DefaultJsonSchemaFactory.kt index 657a38a8..f1b1c88b 100644 --- a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/DefaultJsonSchemaFactory.kt +++ b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/DefaultJsonSchemaFactory.kt @@ -52,7 +52,9 @@ object DefaultJsonSchemaFactory : KotlinSerializationSerdeFactory.JsonSchemaFact // In case of nested schemas, compileReferencing also contains self schema... val rootSchemaName = TitleBuilder.BUILDER_SIMPLE( - compiledSchema.typeData, intermediateStep.typeDataById) + compiledSchema.typeData, + intermediateStep.typeDataById, + ) // If schema is not json object, then it's boolean, so we're good no need for // additional manipulation @@ -64,7 +66,9 @@ object DefaultJsonSchemaFactory : KotlinSerializationSerdeFactory.JsonSchemaFact val rootNode = compiledSchema.json as JsonObject // Add $schema rootNode.properties.put( - "\$schema", JsonTextValue("https://json-schema.org/draft/2020-12/schema")) + "\$schema", + JsonTextValue("https://json-schema.org/draft/2020-12/schema"), + ) // Add $defs val definitions = compiledSchema.definitions.filter { it.key != rootSchemaName }.toMutableMap() @@ -89,18 +93,21 @@ object DefaultJsonSchemaFactory : KotlinSerializationSerdeFactory.JsonSchemaFact return@runCatching rootNode } .getOrDefault(JsonObject(mutableMapOf())) - .prettyPrint()) + .prettyPrint() + ) private fun IntermediateJsonSchemaData.writeTitles() { this.entries.forEach { schema -> if (schema.json is JsonObject) { - if ((schema.typeData.isMap || - schema.typeData.isCollection || - schema.typeData.isEnum || - schema.typeData.isInlineValue || - schema.typeData.typeParameters.isNotEmpty() || - schema.typeData.members.isNotEmpty()) && - (schema.json as JsonObject).properties["title"] == null) { + if ( + (schema.typeData.isMap || + schema.typeData.isCollection || + schema.typeData.isEnum || + schema.typeData.isInlineValue || + schema.typeData.typeParameters.isNotEmpty() || + schema.typeData.members.isNotEmpty()) && + (schema.json as JsonObject).properties["title"] == null + ) { (schema.json as JsonObject).properties["title"] = JsonTextValue(TitleBuilder.BUILDER_SIMPLE(schema.typeData, this.typeDataById)) } diff --git a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/KotlinSerializationSerdeFactory.kt b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/KotlinSerializationSerdeFactory.kt index 59b59900..d7d3c5ef 100644 --- a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/KotlinSerializationSerdeFactory.kt +++ b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/KotlinSerializationSerdeFactory.kt @@ -34,7 +34,7 @@ open class KotlinSerializationSerdeFactory @JvmOverloads constructor( private val json: Json = Json.Default, - private val jsonSchemaFactory: JsonSchemaFactory = DefaultJsonSchemaFactory + private val jsonSchemaFactory: JsonSchemaFactory = DefaultJsonSchemaFactory, ) : SerdeFactory { /** Factory to generate json schemas. */ @@ -52,7 +52,7 @@ constructor( class KtTypeTag( val type: KClass<*>, /** Reified type */ - val kotlinType: KType? + val kotlinType: KType?, ) : TypeTag override fun create(typeTag: TypeTag): Serde { @@ -113,7 +113,7 @@ constructor( fun jsonSerde( json: Json = Json.Default, jsonSchemaFactory: JsonSchemaFactory = DefaultJsonSchemaFactory, - serializer: KSerializer + serializer: KSerializer, ): Serde { val schema = jsonSchemaFactory.generateSchema(json, serializer) @@ -128,7 +128,9 @@ constructor( override fun deserialize(value: Slice): T { return json.decodeFromString( - serializer, String(value.toByteArray(), StandardCharsets.UTF_8)) + serializer, + String(value.toByteArray(), StandardCharsets.UTF_8), + ) } override fun contentType(): String { diff --git a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/api.kt b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/api.kt index 8fc38a91..75f0fd1e 100644 --- a/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/api.kt +++ b/sdk-serde-kotlinx/src/main/kotlin/dev/restate/serde/kotlinx/api.kt @@ -18,7 +18,7 @@ import kotlinx.serialization.serializer inline fun jsonSerde( json: Json = Json.Default, jsonSchemaFactory: KotlinSerializationSerdeFactory.JsonSchemaFactory = - KotlinSerializationSerdeFactory.JsonSchemaFactory.NOOP + KotlinSerializationSerdeFactory.JsonSchemaFactory.NOOP, ): Serde { @Suppress("UNCHECKED_CAST") return when (typeOf()) { diff --git a/sdk-serde-kotlinx/src/test/kotlin/dev/restate/serde/kotlinx/KotlinxSerdeTest.kt b/sdk-serde-kotlinx/src/test/kotlin/dev/restate/serde/kotlinx/KotlinxSerdeTest.kt index 3250ca04..4583a389 100644 --- a/sdk-serde-kotlinx/src/test/kotlin/dev/restate/serde/kotlinx/KotlinxSerdeTest.kt +++ b/sdk-serde-kotlinx/src/test/kotlin/dev/restate/serde/kotlinx/KotlinxSerdeTest.kt @@ -28,147 +28,152 @@ class KotlinxSerdeTest { @Serializable data class RecursiveTemplateCircular( val rec: RecursiveTemplateOtherCircular? = null, - val value: V + val value: V, ) @Serializable data class RecursiveTemplateOtherCircular( val rec: RecursiveTemplateCircular? = null, - val value: V + val value: V, ) @Test fun schemaGenWithPrimitive() { testSchemaGen( """ - { - "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", - "type": "string" - } - """ - .trimIndent()) + { + "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", + "type": "string" + } + """ + .trimIndent() + ) } @Test fun schemaGenWithNullablePrimitive() { testSchemaGen( """ - { - "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", - "type": ["string", "null"] - } - """ - .trimIndent()) + { + "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", + "type": ["string", "null"] + } + """ + .trimIndent() + ) } @Test fun schemaGenWithRecursive() { testSchemaGen( """ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "rec": { - "${'$'}ref": "#/" - }, - "value": { - "type": "string" - } - }, - "title": "Recursive", - "${'$'}schema": "https://json-schema.org/draft/2020-12/schema" - } - """ - .trimIndent()) + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "rec": { + "${'$'}ref": "#/" + }, + "value": { + "type": "string" + } + }, + "title": "Recursive", + "${'$'}schema": "https://json-schema.org/draft/2020-12/schema" + } + """ + .trimIndent() + ) } @Test fun schemaGenWithRecursiveCircular() { testSchemaGen( """ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "rec": { - "${'$'}ref": "#/${'$'}defs/RecursiveOtherCircular" - }, - "value": { - "type": "string" - } - }, - "title": "RecursiveCircular", - "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", - "${'$'}defs": { - "RecursiveOtherCircular": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "rec": { - "${'$'}ref": "#/" - }, - "value": { - "type": "string" - } - }, - "title": "RecursiveOtherCircular" - } - } - } - """ - .trimIndent()) + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "rec": { + "${'$'}ref": "#/${'$'}defs/RecursiveOtherCircular" + }, + "value": { + "type": "string" + } + }, + "title": "RecursiveCircular", + "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", + "${'$'}defs": { + "RecursiveOtherCircular": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "rec": { + "${'$'}ref": "#/" + }, + "value": { + "type": "string" + } + }, + "title": "RecursiveOtherCircular" + } + } + } + """ + .trimIndent() + ) } @Test fun schemaGenWorksWithNestedRecursionTemplated() { testSchemaGen>( """ - { - "type": "object", - "required": [ - "value" - ], - "properties": { - "rec": { - "${'$'}ref": "#/${'$'}defs/RecursiveTemplateOtherCircular" - }, - "value": { - "type": "integer", - "minimum": -2147483648, - "maximum": 2147483647 - } - }, - "title": "RecursiveTemplateCircular", - "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", - "${'$'}defs": { - "RecursiveTemplateOtherCircular": { - "type": "object", - "required": [ - "value" - ], - "properties": { - "rec": { - "${'$'}ref": "#/" - }, - "value": { - "type": "integer", - "minimum": -2147483648, - "maximum": 2147483647 - } - }, - "title": "RecursiveTemplateOtherCircular" - } - } - } - """ - .trimIndent()) + { + "type": "object", + "required": [ + "value" + ], + "properties": { + "rec": { + "${'$'}ref": "#/${'$'}defs/RecursiveTemplateOtherCircular" + }, + "value": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + } + }, + "title": "RecursiveTemplateCircular", + "${'$'}schema": "https://json-schema.org/draft/2020-12/schema", + "${'$'}defs": { + "RecursiveTemplateOtherCircular": { + "type": "object", + "required": [ + "value" + ], + "properties": { + "rec": { + "${'$'}ref": "#/" + }, + "value": { + "type": "integer", + "minimum": -2147483648, + "maximum": 2147483647 + } + }, + "title": "RecursiveTemplateOtherCircular" + } + } + } + """ + .trimIndent() + ) } inline fun testSchemaGen(expectedSchema: String) { diff --git a/sdk-spring-boot-kotlin-starter/build.gradle.kts b/sdk-spring-boot-kotlin-starter/build.gradle.kts index de9939f8..2b7d6a12 100644 --- a/sdk-spring-boot-kotlin-starter/build.gradle.kts +++ b/sdk-spring-boot-kotlin-starter/build.gradle.kts @@ -28,4 +28,5 @@ dependencies { testImplementation(project(":sdk-core")) testImplementation(libs.jackson.annotations) testImplementation(libs.jackson.databind) + testRuntimeOnly(libs.junit.platform.launcher) } diff --git a/sdk-spring-boot-kotlin-starter/src/test/kotlin/dev/restate/sdk/springboot/kotlin/RestateHttpEndpointBeanTest.kt b/sdk-spring-boot-kotlin-starter/src/test/kotlin/dev/restate/sdk/springboot/kotlin/RestateHttpEndpointBeanTest.kt index 68d44f5f..165dc314 100644 --- a/sdk-spring-boot-kotlin-starter/src/test/kotlin/dev/restate/sdk/springboot/kotlin/RestateHttpEndpointBeanTest.kt +++ b/sdk-spring-boot-kotlin-starter/src/test/kotlin/dev/restate/sdk/springboot/kotlin/RestateHttpEndpointBeanTest.kt @@ -23,7 +23,8 @@ import org.springframework.boot.test.context.SpringBootTest @SpringBootTest( classes = [RestateHttpEndpointBean::class, Greeter::class], - properties = ["restate.sdk.http.port=0"]) + properties = ["restate.sdk.http.port=0"], +) class RestateHttpEndpointBeanTest { @Autowired lateinit var restateHttpEndpointBean: RestateHttpEndpointBean @@ -41,10 +42,12 @@ class RestateHttpEndpointBeanTest { .GET() .version(HttpClient.Version.HTTP_2) .uri( - URI.create("http://localhost:${restateHttpEndpointBean.actualPort()}/discover")) + URI.create("http://localhost:${restateHttpEndpointBean.actualPort()}/discover") + ) .header("Accept", "application/vnd.restate.endpointmanifest.v1+json") .build(), - HttpResponse.BodyHandlers.ofString()) + HttpResponse.BodyHandlers.ofString(), + ) assertThat(response.version()).isEqualTo(HttpClient.Version.HTTP_2) assertThat(response.statusCode()).isEqualTo(200) diff --git a/sdk-spring-boot-starter/build.gradle.kts b/sdk-spring-boot-starter/build.gradle.kts index 8f263b0e..87e83596 100644 --- a/sdk-spring-boot-starter/build.gradle.kts +++ b/sdk-spring-boot-starter/build.gradle.kts @@ -37,6 +37,7 @@ dependencies { testImplementation(libs.jackson.databind) testImplementation(project(":sdk-serde-jackson")) testImplementation(project(":sdk-testing")) + testRuntimeOnly(libs.junit.platform.launcher) } tasks.withType { @@ -46,5 +47,6 @@ tasks.withType { listOf( "-parameters", "-Adev.restate.codegen.disabledClasses=${disabledClassesCodegen.joinToString(",")}", - )) + ) + ) } diff --git a/sdk-spring-boot/build.gradle.kts b/sdk-spring-boot/build.gradle.kts index 6e9397eb..30700cd1 100644 --- a/sdk-spring-boot/build.gradle.kts +++ b/sdk-spring-boot/build.gradle.kts @@ -39,6 +39,7 @@ dependencies { testImplementation(libs.spring.boot.starter) testImplementation(libs.spring.boot.starter.json) testImplementation(libs.spring.boot.starter.test) + testRuntimeOnly(libs.junit.platform.launcher) } tasks.withType { options.compilerArgs.add("-parameters") } diff --git a/sdk-testing/build.gradle.kts b/sdk-testing/build.gradle.kts index df84ed11..a06d1536 100644 --- a/sdk-testing/build.gradle.kts +++ b/sdk-testing/build.gradle.kts @@ -24,4 +24,5 @@ dependencies { testImplementation(libs.assertj) testImplementation(libs.junit.jupiter) testImplementation(libs.log4j.core) + testRuntimeOnly(libs.junit.platform.launcher) } diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/FailingImpl.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/FailingImpl.kt index 362812a4..e3edf4d7 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/FailingImpl.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/FailingImpl.kt @@ -36,7 +36,7 @@ class FailingImpl : Failing { override suspend fun callTerminallyFailingCall( context: ObjectContext, - errorMessage: String + errorMessage: String, ): String { LOG.info("Invoked failAndHandle") @@ -66,7 +66,7 @@ class FailingImpl : Failing { override suspend fun sideEffectSucceedsAfterGivenAttempts( context: ObjectContext, - minimumAttempts: Int + minimumAttempts: Int, ): Int = context.runBlock( name = "failing_side_effect", @@ -74,19 +74,20 @@ class FailingImpl : Failing { retryPolicy { initialDelay = 10.milliseconds exponentiationFactor = 1.0f - }) { - val currentAttempt = eventualSuccessSideEffectCalls.incrementAndGet() - if (currentAttempt >= 4) { - eventualSuccessSideEffectCalls.set(0) - return@runBlock currentAttempt - } else { - throw IllegalArgumentException("Failed at attempt: $currentAttempt") - } - } + }, + ) { + val currentAttempt = eventualSuccessSideEffectCalls.incrementAndGet() + if (currentAttempt >= 4) { + eventualSuccessSideEffectCalls.set(0) + return@runBlock currentAttempt + } else { + throw IllegalArgumentException("Failed at attempt: $currentAttempt") + } + } override suspend fun sideEffectFailsAfterGivenAttempts( context: ObjectContext, - retryPolicyMaxRetryCount: Int + retryPolicyMaxRetryCount: Int, ): Int { try { context.runBlock( @@ -96,10 +97,11 @@ class FailingImpl : Failing { initialDelay = 10.milliseconds exponentiationFactor = 1.0f maxAttempts = retryPolicyMaxRetryCount - }) { - val currentAttempt = eventualFailureSideEffectCalls.incrementAndGet() - throw IllegalArgumentException("Failed at attempt: $currentAttempt") - } + }, + ) { + val currentAttempt = eventualFailureSideEffectCalls.incrementAndGet() + throw IllegalArgumentException("Failed at attempt: $currentAttempt") + } } catch (_: TerminalException) { return eventualFailureSideEffectCalls.get() } diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/Main.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/Main.kt index 8ae14aba..6d556b3d 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/Main.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/Main.kt @@ -41,7 +41,8 @@ val KNOWN_SERVICES_FACTORIES: Map Any> = ServiceInterpreterHelperHandlers.Metadata.SERVICE_NAME to { ServiceInterpreterHelperImpl() - }) + }, + ) val NEEDS_EXPERIMENTAL_CONTEXT: Set = setOf() @@ -60,7 +61,8 @@ fun main(args: Array) { val fqsn = svc.trim { it <= ' ' } bind( KNOWN_SERVICES_FACTORIES[fqsn]?.invoke() - ?: throw IllegalStateException("Service $fqsn not implemented")) + ?: throw IllegalStateException("Service $fqsn not implemented") + ) } } diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/ProxyImpl.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/ProxyImpl.kt index 86a5a0ef..21fba1b2 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/ProxyImpl.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/ProxyImpl.kt @@ -57,7 +57,8 @@ class ProxyImpl : Proxy { request.proxyRequest.toTarget(), Serde.RAW, Serde.SLICE, - request.proxyRequest.message) + request.proxyRequest.message, + ) .also { if (request.proxyRequest.idempotencyKey != null) { it.idempotencyKey = request.proxyRequest.idempotencyKey @@ -70,7 +71,8 @@ class ProxyImpl : Proxy { request.proxyRequest.toTarget(), Serde.RAW, Serde.RAW, - request.proxyRequest.message) + request.proxyRequest.message, + ) .also { if (request.proxyRequest.idempotencyKey != null) { it.idempotencyKey = request.proxyRequest.idempotencyKey diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/VirtualObjectCommandInterpreterImpl.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/VirtualObjectCommandInterpreterImpl.kt index 4b81d175..81414fdb 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/VirtualObjectCommandInterpreterImpl.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/VirtualObjectCommandInterpreterImpl.kt @@ -25,7 +25,7 @@ class VirtualObjectCommandInterpreterImpl : VirtualObjectCommandInterpreter { override suspend fun interpretCommands( context: ObjectContext, - req: VirtualObjectCommandInterpreter.InterpretRequest + req: VirtualObjectCommandInterpreter.InterpretRequest, ): String { LOG.info("Interpreting commands {}", req) @@ -93,23 +93,25 @@ class VirtualObjectCommandInterpreterImpl : VirtualObjectCommandInterpreter { override suspend fun resolveAwakeable( context: SharedObjectContext, - resolveAwakeable: VirtualObjectCommandInterpreter.ResolveAwakeable + resolveAwakeable: VirtualObjectCommandInterpreter.ResolveAwakeable, ) { context .awakeableHandle( context.get("awk-${resolveAwakeable.awakeableKey}") - ?: throw TerminalException("awakeable is not registerd yet")) + ?: throw TerminalException("awakeable is not registerd yet") + ) .resolve(resolveAwakeable.value) } override suspend fun rejectAwakeable( context: SharedObjectContext, - rejectAwakeable: VirtualObjectCommandInterpreter.RejectAwakeable + rejectAwakeable: VirtualObjectCommandInterpreter.RejectAwakeable, ) { context .awakeableHandle( context.get("awk-${rejectAwakeable.awakeableKey}") - ?: throw TerminalException("awakeable is not registerd yet")) + ?: throw TerminalException("awakeable is not registerd yet") + ) .reject(rejectAwakeable.reason) } diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/CancelTest.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/CancelTest.kt index aff63377..fbc524ba 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/CancelTest.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/CancelTest.kt @@ -16,7 +16,7 @@ import kotlinx.serialization.Serializable enum class BlockingOperation { CALL, SLEEP, - AWAKEABLE + AWAKEABLE, } interface CancelTest { diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Failing.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Failing.kt index 860c2691..b2e68240 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Failing.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Failing.kt @@ -33,7 +33,7 @@ interface Failing { @Handler suspend fun sideEffectSucceedsAfterGivenAttempts( context: ObjectContext, - minimumAttempts: Int + minimumAttempts: Int, ): Int /** @@ -45,6 +45,6 @@ interface Failing { @Handler suspend fun sideEffectFailsAfterGivenAttempts( context: ObjectContext, - retryPolicyMaxRetryCount: Int + retryPolicyMaxRetryCount: Int, ): Int } diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Proxy.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Proxy.kt index eb6f0242..82b51a54 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Proxy.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/Proxy.kt @@ -20,7 +20,7 @@ data class ProxyRequest( // Bytes are encoded as array of numbers val message: ByteArray, val delayMillis: Int? = null, - val idempotencyKey: String? = null + val idempotencyKey: String? = null, ) @Serializable @@ -32,7 +32,7 @@ data class ManyCallRequest( * If await at the end, then perform the call as regular call, and collect all the futures to * wait at the end, before returning, instead of awaiting them immediately. */ - val awaitAtTheEnd: Boolean + val awaitAtTheEnd: Boolean, ) @Service diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/VirtualObjectCommandInterpreter.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/VirtualObjectCommandInterpreter.kt index 59292d72..fcd2ae31 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/VirtualObjectCommandInterpreter.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/VirtualObjectCommandInterpreter.kt @@ -45,9 +45,7 @@ interface VirtualObjectCommandInterpreter { data class AwaitAny(val commands: List) : Command // Returns the result - @Serializable - @SerialName("awaitOne") - data class AwaitOne(val command: AwaitableCommand) : Command + @Serializable @SerialName("awaitOne") data class AwaitOne(val command: AwaitableCommand) : Command // This is serialized as `{"type": "awaitAwakeableOrTimeout", ...}` // The timeout throws a terminal error with "await-timeout" string in it diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/interpreter.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/interpreter.kt index 3eb63cfc..41090d34 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/interpreter.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/contracts/interpreter.kt @@ -243,7 +243,7 @@ interface ObjectInterpreter { @Serializable data class IncrementViaAwakeableDanceRequest( val interpreter: InterpreterId, - val txPromiseId: String + val txPromiseId: String, ) @Service diff --git a/test-services/src/main/kotlin/dev/restate/sdk/testservices/interpreter.kt b/test-services/src/main/kotlin/dev/restate/sdk/testservices/interpreter.kt index 26a44738..1541bd26 100644 --- a/test-services/src/main/kotlin/dev/restate/sdk/testservices/interpreter.kt +++ b/test-services/src/main/kotlin/dev/restate/sdk/testservices/interpreter.kt @@ -32,19 +32,20 @@ suspend fun checkAwaitable( actual: DurableFuture, expected: T, cmdIndex: Int, - interpreterCommand: InterpreterCommand + interpreterCommand: InterpreterCommand, ) { val result = actual.await() if (result != expected) { throw TerminalException( - "Awaited promise mismatch. got '$result' expected '$expected'; command at index $cmdIndex was $interpreterCommand") + "Awaited promise mismatch. got '$result' expected '$expected'; command at index $cmdIndex was $interpreterCommand" + ) } } suspend fun checkAwaitableFails( actual: DurableFuture, cmdIndex: Int, - interpreterCommand: InterpreterCommand + interpreterCommand: InterpreterCommand, ) { try { actual.await() @@ -52,7 +53,8 @@ suspend fun checkAwaitableFails( return } throw TerminalException( - "Awaited promise mismatch. should fail but instead got ${actual.await()}; command at index $cmdIndex was $interpreterCommand") + "Awaited promise mismatch. should fail but instead got ${actual.await()}; command at index $cmdIndex was $interpreterCommand" + ) } fun cmdStateKey(key: Int): StateKey { @@ -67,7 +69,10 @@ class ObjectInterpreterImpl(private val layer: Int) : ObjectInterpreter { val originalDefinition = ObjectInterpreterServiceDefinitionFactory().create(ObjectInterpreterImpl(layer), null) return ServiceDefinition.of( - interpreterName(layer), originalDefinition.serviceType, originalDefinition.handlers) + interpreterName(layer), + originalDefinition.serviceType, + originalDefinition.handlers, + ) } } @@ -87,7 +92,8 @@ class ObjectInterpreterImpl(private val layer: Int) : ObjectInterpreter { val p = promises.remove(cmd.index) ?: throw TerminalException( - "ObjectInterpreterL$layer: can not find a promise for the id ${cmd.index}.") + "ObjectInterpreterL$layer: can not find a promise for the id ${cmd.index}." + ) // Await on promise, this will under the hood check the promise result p() } @@ -98,7 +104,9 @@ class ObjectInterpreterImpl(private val layer: Int) : ObjectInterpreter { interpretTarget(layer + 1, cmd.key.toString()), ObjectInterpreterHandlers.Metadata.Serde.INTERPRET_INPUT, ObjectInterpreterHandlers.Metadata.Serde.INTERPRET_OUTPUT, - cmd.program)) + cmd.program, + ) + ) promises[i] = { awaitable.await() } } is CallService -> { @@ -129,7 +137,8 @@ class ObjectInterpreterImpl(private val layer: Int) : ObjectInterpreter { // Dancing in the mooonlight! val awakeable = ctx.awakeable() ServiceInterpreterHelperHandlers.incrementViaAwakeableDance( - IncrementViaAwakeableDanceRequest(interpreterId(ctx), awakeable.id)) + IncrementViaAwakeableDanceRequest(interpreterId(ctx), awakeable.id) + ) .send(ctx) val theirPromiseIdForUsToResolve = awakeable.await() ctx.awakeableHandle(theirPromiseIdForUsToResolve).resolve("ok") @@ -147,7 +156,8 @@ class ObjectInterpreterImpl(private val layer: Int) : ObjectInterpreter { } if (!caught) { throw TerminalException( - "Test assertion failed, was expected to get a terminal error. Layer $layer, Command $i") + "Test assertion failed, was expected to get a terminal error. Layer $layer, Command $i" + ) } } is RecoverTerminalCallMaybeUnAwaited -> { @@ -213,7 +223,9 @@ class ServiceInterpreterHelperImpl : ServiceInterpreterHelper { interpretTarget(id.layer, id.key), ObjectInterpreterHandlers.Metadata.Serde.INTERPRET_INPUT, Serde.SLICE, - Program(listOf(IncrementStateCounter())))) + Program(listOf(IncrementStateCounter())), + ) + ) } override suspend fun resolveAwakeable(ctx: Context, id: String) { @@ -226,7 +238,7 @@ class ServiceInterpreterHelperImpl : ServiceInterpreterHelper { override suspend fun incrementViaAwakeableDance( ctx: Context, - req: IncrementViaAwakeableDanceRequest + req: IncrementViaAwakeableDanceRequest, ) { // // 1. create an awakeable that we will be blocked on @@ -249,6 +261,8 @@ class ServiceInterpreterHelperImpl : ServiceInterpreterHelper { interpretTarget(req.interpreter.layer, req.interpreter.key), ObjectInterpreterHandlers.Metadata.Serde.INTERPRET_INPUT, Serde.SLICE, - Program(listOf(IncrementStateCounter())))) + Program(listOf(IncrementStateCounter())), + ) + ) } }