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

Stacking Layers — Composition Patterns

Layer composition is explicit. Use Stack / and_then for HList-style layers, and merge / provide / provide_merge for ServiceContext layers.

Independent HList Layers

use effectful::{LayerBuild, Stack};

let stack = Stack(config_layer, logger_layer);
let env = stack.build()?; // Cons<ConfigOutput, Cons<LoggerOutput, Nil>>

The two layers must have the same error type.

Dependent HList Layers

Use LayerExt::and_then or StackThen when the second layer needs the first layer’s output.

use effectful::{LayerBuild, LayerExt, LayerFn, LayerFnFrom};

let config = LayerFn(|| Ok(Config::from_env()?));
let db = LayerFnFrom(|config: &Config| Ok(Database::connect(config.db_url())?));

let env = config.and_then(db).build()?;

ServiceContext merge

For derive-service layers, merge builds independent layers and combines their ServiceContexts.

let app_layer = config_layer.merge(logger_layer);
let context = run_blocking(app_layer.build(), ())?;

ServiceContext provide

Use provide when one layer needs services from another layer and you want to hide provider output.

let db_with_config = db_layer.provide(config_layer);
let context = run_blocking(db_with_config.build(), ())?;

Use provide_merge when you want both provider and dependent services in the final context.

let app_layer = db_layer.provide_merge(config_layer);

Providing to Effects

Effect::provide(layer) exists for effects whose environment is ServiceContext.

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

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