Prelude vs Layer
The prelude and layer fields in WorkerdActorRuntime.make(...) serve different lifetimes.
Use prelude for long-lived infrastructure:
- database access
- config
- logging
- asset bindings
- Cloudflare service bindings
Use layer for short-lived context derived from the current client-specific actor invocation:
- current user id
- current authorization
Derive request context
The next example builds a layer that provides an actor-specific CurrentUserId derived from two different actor
definitions.
import { Context, Effect, Layer, Schema as S } from "effect"
import { ChatActor } from "../chat/ChatActor.ts"
import { LobbyActor } from "../lobby/LobbyActor.ts"
const UserId = S.String.pipe(S.brand("UserId"))
export class CurrentUserId extends Context.Service<CurrentUserId, typeof UserId.Type>()("CurrentUserId") {}
// Use the actor name as the id.
export const layerLobby = Effect.gen(function* () {
const { name } = yield* LobbyActor
return name
}).pipe(Layer.effect(CurrentUserId))
// Use the current client attachment as the id.
export const layerChat = Effect.gen(function* () {
const { currentClient } = yield* ChatActor
const { userId } = yield* currentClient.attachments
return userId
}).pipe(Layer.effect(CurrentUserId))In Effect v4, context is defined with Context.Service<Self, A>()(id). This replaces Context.Tag from earlier
versions.
Read Actor Context for the values available through yield* ActorTag.