cordis-loader 0.0.2

Config-file driven plugin loader for the cordis-rs plugin framework
Documentation

Config-file driven plugin loader for cordis-rs.

This crate is the assembly half of porting upstream Cordis' loader: it connects cordis-include's entry trees to cordis fibers. Everything a config-driven cordis application needs is re-exported here — depend on cordis-loader alone.

How it works

  • Static registry ([PluginRegistry]) replaces upstream's dynamic import(name): register plugins at startup, entries resolve by name. The group builtin is pre-registered.
  • Startup: [Loader::open] reads the entry file (writing initial when missing), builds the [EntryTree], and starts every enabled entry — group entries as cordis_group::Group fibers, children beneath their parent group's context, so disposing a group cascades.
  • Config: entries carry a cordis_include::Node config (never ()); loader plugins read it via config.downcast::<Node>(). ${{ env.X }} templates expand at hand-off time; the file keeps the raw text.
  • Reload ([Loader::reload], wired to the watch feature): re-read the file, diff the tree, and reconcile fibers — created entries start, removed subtrees stop, moved entries restart under their new parent, config-only changes patch in place via Fiber::update_value.
  • Inject: an entry's inject list is merged into the plugin's own declaration, so the core fiber machinery reconciles entries when services come and go — "hot-swapped service restarts its dependents" for free.
  • Self-kill vs. removal: a fiber that reaches Disposed outside loader operation was killed by its own plugin; the loader persists disabled: true for that entry. Removing an entry from the file just stops it.
  • Write-back: [Loader::update_config] is the runtime entry point — it updates the fiber and persists the config. Reloads never echo back (file-level suspend).

Example

use cordis_loader::{Loader, LoaderConfig, PluginRegistry};

let root = cordis::Context::new();
let mut registry = PluginRegistry::new();
// registry.register_plugin(my_plugin);  // your plugins, by name
let config = LoaderConfig::new("cordis.yml").with_registry(registry);
let loader = Loader::open(&root, config)?;
# assert!(loader.tree().entries().is_empty());
# Ok::<(), cordis_loader::LoaderError>(())

Register the plugins first (the group builtin is pre-registered), then open; plugins registered later via [Loader::register_plugin] are picked up by the next [Loader::reload].

Not in scope yet

The import entry kind (mounting a sub-file), isolate/service migration, the loader/entry-init-style event family, and debounced merged writes are future work.