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

blockwatcher-embed

blockwatcher-embed is the in-process composition façade: it folds every compiled-in module family into one ModuleCatalog, and it re-exports the engine types a host needs to boot and stop without linking the blockwatcher binary. The binary itself calls build_catalog here rather than keeping a second registrar (crates/blockwatcher/src/run.rs).

It sits in the glue ring, the same ring as the binary: it may depend on blockwatcher-core, and scripts/check-dep-graph.sh allowlists it that way. It does not depend on blockwatcher-api, axum, the metrics HTTP listener, CLI parsing, or process signals.

Its production dependencies are exactly the ALLOW_BLOCKWATCHER_EMBED entry scripts/check-dep-graph.sh lists (crates/blockwatcher-embed/Cargo.toml):

  • blockwatcher-core: Engine, EngineDeps, Engine::start, ControlHandle, ModuleCatalog
  • blockwatcher-storage: always folded into the catalog (memory, sqlite); not behind a feature
  • blockwatcher-gates: always folded into the catalog (threshold, max_once); not behind a feature — there is no gates flag
  • blockwatcher-expr, blockwatcher-evm, blockwatcher-sinks: optional (dep: in [features]), one per feature flag, mirroring the binary

The family exemption list (FAMILY_EXEMPT_BLOCKWATCHER_EMBED) covers the module crates this façade links (alloy, reqwest, hyper, tower-http, rusqlite) and not axum: embed never serves HTTP.

Embedding blockwatcher in a host process already covers this crate from a host’s side: the boot recipe, an in-process Sink, and how shutdown differs from the binary. This page does not restate that recipe; it covers what the crate actually exports, which feature flag removes which registration, and where it sits in the dependency graph.

Key takeaways

  • blockwatcher-embed is glue, not a module: it may depend on blockwatcher-core, and it is the one place module families are registered.
  • Default features (evm, expr, sinks) mirror the binary; storage and gate modules (threshold, max_once) are always present. There is no gates feature: turning a gate module off is not a compile-time switch; an unknown gate.module at write is 422 listing catalog names.
  • It re-exports build_catalog, DEFAULT_MATCHER (when expr is on), Engine, EngineDeps, EngineConfig, EngineError, and ControlHandle. It does not wrap Engine::start.
  • The binary is a client of this crate for catalog construction. Nothing in the workspace depends on embed except the binary.

Responsibilities

  • Registers every compiled-in module family into one ModuleCatalog, feature-gated so what a build can select is exactly what it linked (catalog.rs).
  • Re-exports the small set of engine types a host needs for the happy path (lib.rs).
  • Forwards the binary’s evm / expr / sinks feature flags onto the same optional module crates, so a binary built without evm also builds embed without evm (crates/blockwatcher/Cargo.toml).

Not this crate’s job: parsing CLI or instance config, seeding a directory, binding listeners, installing SIGTERM/SIGINT, or serving HTTP or Prometheus (blockwatcher binary, blockwatcher-api, blockwatcher-metrics); running a pipeline or deciding when a checkpoint advances (blockwatcher-core); implementing any module a catalog can select (each lives in its own module crate).

Key types and functions

NameKindRole
build_catalogfnFolds every compiled-in family’s get_all() into one ModuleCatalog, feature-gated per family (catalog.rs)
DEFAULT_MATCHERconst"expr", behind feature expr. The name build_catalog registers for the matcher family; the binary’s config fallback uses it so an unset [engine].matcher selects the same module (catalog.rs)
Engine, EngineDeps, EngineConfig, EngineErrorre-exportThe same types blockwatcher-core publishes; Engine::start takes EngineDeps by value
ControlHandlere-exportThe one path a running engine’s resources change through

Feature-flag wiring

Cargo.toml’s optional features each gate one dep: entry, all on by default:

[features]
default = ["evm", "expr", "sinks"]
evm = ["dep:blockwatcher-evm"]
expr = ["dep:blockwatcher-expr"]
sinks = ["dep:blockwatcher-sinks"]

build_catalog (catalog.rs) is where the effect of each flag is entirely mechanical: a #[cfg(feature = "...")] block around one fold, family by family:

FeatureOff, build_catalog no longer registers
evmblockwatcher_evm::sources::get_all() (evm-rpc, evm-mempool) and blockwatcher_evm::decoders::get_all() (evm)
exprblockwatcher_expr::matchers::get_all() (expr)
sinksblockwatcher_sinks::registry::sinks::get_all() (webhook, script, log)

Storage’s own registration, blockwatcher_storage::registry::storages::get_all() (memory, sqlite), is not behind any feature: blockwatcher-storage is a plain, non-optional dependency. Gate modules, blockwatcher_gates::registry::gates::get_all() (threshold, max_once), are the same: always registered.

A build missing a feature does not merely fail to offer the module by name; the factory function itself is absent, since the whole fold is compiled out. A config naming a module a build didn’t link refuses at catalog lookup time with the alternatives that build actually carries (catalog.rs’s own tests, an_unknown_storage_module_is_refused_naming_what_this_build_carries).

Neighbours

blockwatcher-embed depends on, in production:

  • blockwatcher-core
  • blockwatcher-storage
  • blockwatcher-gates
  • blockwatcher-expr (feature expr, on by default)
  • blockwatcher-evm (feature evm, on by default)
  • blockwatcher-sinks (feature sinks, on by default)

and, in [dev-dependencies] only:

  • tokio (macros/rt features): the catalog construction tests

The following crate depends on it directly (per the dependency table):

  • blockwatcher (binary): calls build_catalog at boot, seed validation, and checkpoint prune; forwards its own feature flags onto this crate’s matching features.

Reading the source

  1. lib.rs: the crate doc comment (why hosts depend here rather than assembling a catalog themselves) and the re-export surface.
  2. catalog.rs: build_catalog, and read it beside Feature-flag wiring above.