Expand description
Hand-rolled #[repr(C)] plugin vtable.
Design rationale: see ADR-001 / docs/abi-evolution.md (TBD). In short:
abi_stable’s prefix-type model rejects loads where the host’s vtable
has more fields than the plugin’s, blocking the host-grows-faster
direction we need. The hand-rolled C-style vtable with a leading
api_version: u32 field, version-gated host access, and an
append-only evolution discipline gives us bidirectional ABI compat
without a third-party load-time check that fights us.
§Layout invariants (load-bearing)
api_versionMUST be the first field.- Existing fields MUST NOT be reordered or removed in any future crate version. New fields MUST be appended after the existing ones.
PLUGIN_API_VERSIONincrements by 1 each time a new field is appended and the corresponding accessor lands.- Hosts MUST read
api_versionbefore accessing any field beyond the v1 baseline. Reading newer fields on a plugin that reports a lowerapi_versionis undefined behavior — the plugin’s allocation does not include those bytes.
See crates/hub/tests/abi_matrix.rs for the regression test that
enforces invariants 1–3 by loading every published plugin version
against the current hub binary.
Structs§
- PluginV
Table - The function table a plugin shared library exports.
Constants§
- GET_
PLUGIN_ VTABLE_ SYMBOL - Symbol name the hub looks up via
dlsymafterdlopen. - PLUGIN_
API_ VERSION - Latest API version this crate’s
PluginVTableexposes. Plugin authors set this as theapi_versionfield. When future versions of this crate append a field, this constant bumps by 1. - PLUGIN_
API_ VERSION_ V1 - API version corresponding to the v1 baseline (initial release of the
hand-rolled vtable). Every field declared in
PluginVTableis part of v1 and is present on every plugin built against this crate. - PLUGIN_
API_ VERSION_ V2 - API version v2: adds
set_metric_recorderso plugins can emit Prometheus metrics through the hub’s existing recorder. Plugins built against v2 keep loading on v1 hubs (the hub ignores the field because it doesn’t know it exists); plugins built against v1 keep loading on v2 hubs (the hub gates access onapi_version >= 2and skips the install for v1 plugins). - PLUGIN_
API_ VERSION_ V3 - API version v3: adds
drainso the hub can wait for a plugin’s fire-and-forget background work (mirror’sruntime.spawn’d HTTP dispatches, otel’s batched exporter queue, etc.) to quiesce beforeshutdownis invoked on a reload. Plugins that complete all work insideprocess()(coraza, external-auth, sso-auth, …) get thedefine_plugin!macro’s default thunk which returns immediately — no in-flight state, nothing to wait for. Plugins with background work overridedrainto block until their state is quiescent or the supplied deadline elapses.
Type Aliases§
- GetPluginV
Table Fn - Type of the exported entry-point symbol.