Introduction¶
Remote Procedure Call (RPC) interfaces define the interface a given micro-service exposes via the network. The
interface describes how each call should be made on a concrete RPC backend. Each micro-service define the interfaces
in the api
package. You can read more about the overall structure of a micro-service
here.
⚠️WARNING: This document, while still true, has mostly been superseded by shorter versions for defining a call. These are described in more detail here.
The interfaces themselves are defined using a Kotlin DSL. If you are unfamiliar with the syntax it might help to read this article.
Example: Defining a remote procedure call (RPC) interface
// Stored in /backend/avatar-service/api/src/main/kotlin/Avatars.kt
data class SerializedAvatar(/* left out for brevity */)
typealias UpdateRequest = SerializedAvatar
typealias UpdateResponse = Unit
typealias FindRequest = Unit
typealias FindResponse = SerializedAvatar
object Avatars : CallDescriptionContainer("avatar") {
val baseContext = "/api/avatar"
val update = call<UpdateRequest, UpdateResponse, CommonErrorMessage>("update") {
auth {
access = AccessRight.READ_WRITE
}
http {
method = HttpMethod.Post
path {
using(baseContext)
+"update"
}
body { bindEntireRequestFromBody() }
}
}
val findAvatar = call<FindRequest, FindResponse, CommonErrorMessage>("findAvatar") {
auth {
access = AccessRight.READ
}
http {
method = HttpMethod.Get
path {
using(baseContext)
+"find"
}
}
}
}
Example: Calling a remote procedure call
val avatar: FindResponse = Avatars.findAvatar.call(FindRequest, serviceClient).orThrow()
Example: Adding a dependency on another service api
package
// build.gradle.kts of the service
dependencies {
implementation(project(":avatar-service:api"))
}
Anatomy of a remote procedure call¶
A remote procedure calls consists of two parts:
The header
The body
In the header we define the calls types. The system uses the types in serialization of the data
as well as type-safety. The types themselves must also be stored in the api
component.
Figure: The remote procedure call header contains a name and three types associated with it (request, success, error).
In the body of the remote procedure call definition we place one or more blocks. Each block provides instructions to both the RPC client and the server. For example, the server uses this information to configure the underlying server implementation (e.g. Ktor) to listen on the correct endpoint. Similarly, the client uses this information to make the correct call on the network.
Figure: The body of an RPC contains several ‘blocks’. Each block helps define how the client and server should treat these calls.
Reference¶
Block | Mandatory | Description |
---|---|---|
auth | ✅ Yes | Provides configuration for authentication and authorization |
audit | ❌ No | The audit block provides a way to change the information which will be written to the audit log |
http | ❌ No | http enables communication of this call via the HTTP backend |
websocket | ❌ No | websocket enables communication of this call via the WebSocket backend |
Note: Even though both http
and websocket
is optional you must select at least one. We recommend that you use
http
for most calls.