KsContext

annotation class KsContext(val binding: KClass<out KsContextBinding<*>>)

Meta-annotation that opts an annotation class into ksrpc's per-call coroutine-context propagation. Apply this to an annotation class together with a binding referencing a concrete KsContextBinding implementation to declare that the annotated KsMethod (or every KsMethod inside an annotated KsService) should propagate a kotlin.coroutines.CoroutineContext.Element value across the wire.

The binding supplies:

Compiler validation:

Code emission for stub-side put-into-context and handler-side read-from-coroutine-context, plus per-transport wire formats, is handled by follow-up work and is intentionally not part of this annotation's contract.

Samples

import com.monkopedia.ksrpc.KsContextBinding
import com.monkopedia.ksrpc.RpcService
import com.monkopedia.ksrpc.annotation.KsContext
import com.monkopedia.ksrpc.annotation.KsMethod
import com.monkopedia.ksrpc.annotation.KsService
import com.monkopedia.ksrpc.ksrpcEnvironment
import com.monkopedia.ksrpc.serialized
import com.monkopedia.ksrpc.toStub
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
import kotlinx.coroutines.withContext

fun main() { 
   //sampleStart 
   // A KsContextBinding pairs a CoroutineContext.Element with a wire key.
// Declare the binding as a named companion on the element type.
val wireKey = RequestId.Key.wireKey // "x-request-id"

// Round-trip: encode to wire, decode from wire
val original = RequestId("abc-123")
val encoded = RequestId.Key.toWire(original)
val decoded = RequestId.Key.fromWire(encoded) 
   //sampleEnd
}
import com.monkopedia.ksrpc.KsContextBinding
import com.monkopedia.ksrpc.RpcService
import com.monkopedia.ksrpc.annotation.KsContext
import com.monkopedia.ksrpc.annotation.KsMethod
import com.monkopedia.ksrpc.annotation.KsService
import com.monkopedia.ksrpc.ksrpcEnvironment
import com.monkopedia.ksrpc.serialized
import com.monkopedia.ksrpc.toStub
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
import kotlinx.coroutines.withContext

fun main() { 
   //sampleStart 
   // @KsContext is a meta-annotation applied to your own annotation.
// Apply the annotation at the service level (all methods) or per-method.
//
// @Authorized              -- applied to SecureService (all methods get it)
// @WithRequestId           -- applied to whoAmI only
//
// The compiler plugin validates that bindings implement KsContextBinding
// and that no two bindings share the same wireKey on a single method. 
   //sampleEnd
}
import com.monkopedia.ksrpc.KsContextBinding
import com.monkopedia.ksrpc.RpcService
import com.monkopedia.ksrpc.annotation.KsContext
import com.monkopedia.ksrpc.annotation.KsMethod
import com.monkopedia.ksrpc.annotation.KsService
import com.monkopedia.ksrpc.ksrpcEnvironment
import com.monkopedia.ksrpc.serialized
import com.monkopedia.ksrpc.toStub
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
import kotlinx.coroutines.withContext

fun main() { 
   //sampleStart 
   // Server handler reads context from the coroutine context.
val service = object : SecureService {
    override suspend fun whoAmI(input: String): String {
        val auth = coroutineContext[AuthorizationToken.Key]
        val reqId = coroutineContext[RequestId.Key]
        return "auth=${auth?.bearer}, reqId=${reqId?.value}"
    }
}

val env = ksrpcEnvironment { }
val serialized = service.serialized(env)
val stub = serialized.toStub<SecureService, String>()

// Client installs context elements using standard withContext.
// The ksrpc runtime propagates bound elements across the wire.
withContext(AuthorizationToken("secret-token") + RequestId("req-42")) {
    val result = stub.whoAmI("hello")
} 
   //sampleEnd
}

Properties

Link copied to clipboard