ServiceContext
A ServiceContext
is a heterogeneous storage type with value semantics for keyed values in a type-safe fashion.
struct ServiceContext
Its values are uniquely identified via ServiceContextKey
s (by type identity). These keys also dictate the type of value allowed for a specific key-value pair through their associated type Value
.
Defining keys and accessing values
ServiceContext keys are defined as types, most commonly case-less enums (as no actual instances are required) which conform to the ServiceContextKey
protocol:
private enum TestIDKey: ServiceContextKey {
typealias Value = String
}
While defining a key, one should also immediately declare an extension on ServiceContext
to allow convenient and discoverable ways to interact with the context item. The extension should take the form of:
extension ServiceContext {
var testID: String? {
get {
self[TestIDKey.self]
} set {
self[TestIDKey.self] = newValue
}
}
}
For consistency, it is recommended to name key types with the ...Key
suffix (e.g. SomethingKey
) and the property used to access a value identifier by such key the prefix of the key (e.g. something
). Please also observe the usual Swift naming conventions, e.g. prefer ID
to Id
etc.
Usage
Using a context container is fairly straight forward, as it boils down to using the prepared computed properties:
var context = ServiceContext.topLevel
// set a new value
context.testID = "abc"
// retrieve a stored value
let testID = context.testID ?? "default"
// remove a stored value
context.testIDKey = nil
Note that normally a context should not be “created” ad-hoc by user code, but rather it should be passed to it from a runtime. A ServiceContext
may already be available to you through ServiceContext.$current when using structured concurrency. Otherwise, for example when working in an HTTP server framework, it is most likely that the context is already passed directly or indirectly (e.g. in a FrameworkContext
).
Accessing all values
The only way to access “all” values in a context is by using the forEach
function. ServiceContext
does not expose more functions on purpose to prevent abuse and treating it as too much of an arbitrary value smuggling container, but only make it convenient for tracing and instrumentation systems which need to access either specific or all items carried inside a context.