Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

What Is a Layer?

An Effect describes a computation that needs an environment. A layer describes how to build values or services that can become that environment.

Two Layer Surfaces

effectful currently exposes two related layer APIs.

LayerFn / LayerBuild
  Builds typed values, often `Tagged<K, V>` cells for HList `Context`s.

Layer<ROut, E, RIn>
  Builds services into `ServiceContext` for derive-service applications.

HList-Style Layer

use effectful::{LayerBuild, LayerFn, tagged};

let db_layer = LayerFn(|| {
    let pool = connect_pool_blocking(database_url)?;
    Ok(tagged::<DatabaseKey, _>(pool))
});

let db_cell = db_layer.build()?;

LayerFn is lazy: construction does nothing; build() runs the constructor.

ServiceContext Layer

use effectful::{Layer, Service};

#[derive(Clone, Service)]
struct Database { /* ... */ }

let db_layer = Layer::succeed(Database::new());
let context = run_blocking(db_layer.build(), ())?;

For dependencies, use Layer::effect and read upstream services from ServiceContext.

let db_layer = Layer::effect("Database", || {
    Config::use_(|config| Database::connect(config.database_url))
});

Providing to Effects

Effect::provide(layer) exists for Effect<_, _, ServiceContext>.

let result = run_blocking(my_app().provide(app_layer), ())?;

For typed Context environments, build the context and pass it directly to run_blocking(effect, env).

Lifecycle

Resource lifecycles are handled by Scope, Pool, and explicit finalizers. Layers are constructors; if a layer creates resources that require cleanup, make that cleanup part of the service design or the surrounding scope.