Skip to main content

ObserverPlugin

Trait ObserverPlugin 

pub trait ObserverPlugin:
    Send
    + Sync
    + 'static {
Show 22 methods // Provided methods fn name(&self) -> &'static str { ... } fn config(&self) -> PluginConfig { ... } fn setup<'life0, 'async_trait>( &'life0 self, _ctx: PluginContext, ) -> Pin<Box<dyn Future<Output = Result<(), PluginSetupError>> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_raw_packet<'life0, 'async_trait>( &'life0 self, _event: RawPacketEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_shred<'life0, 'async_trait>( &'life0 self, _event: ShredEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_dataset<'life0, 'async_trait>( &'life0 self, _event: DatasetEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn accepts_transaction(&self, _event: &TransactionEvent) -> bool { ... } fn accepts_transaction_ref(&self, event: TransactionEventRef<'_>) -> bool { ... } fn transaction_interest( &self, event: &TransactionEvent, ) -> TransactionInterest { ... } fn transaction_interest_ref( &self, event: TransactionEventRef<'_>, ) -> TransactionInterest { ... } fn on_transaction<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn on_transaction_batch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionBatchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn on_transaction_view_batch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionViewBatchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn on_transaction_with_interest<'life0, 'life1, 'async_trait>( &'life0 self, event: &'life1 TransactionEvent, _interest: TransactionInterest, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn accepts_account_touch_ref( &self, _event: AccountTouchEventRef<'_>, ) -> bool { ... } fn on_account_touch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 AccountTouchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait { ... } fn on_slot_status<'life0, 'async_trait>( &'life0 self, _event: SlotStatusEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_reorg<'life0, 'async_trait>( &'life0 self, _event: ReorgEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_recent_blockhash<'life0, 'async_trait>( &'life0 self, _event: ObservedRecentBlockhashEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_cluster_topology<'life0, 'async_trait>( &'life0 self, _event: ClusterTopologyEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn on_leader_schedule<'life0, 'async_trait>( &'life0 self, _event: LeaderScheduleEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... } fn shutdown<'life0, 'async_trait>( &'life0 self, _ctx: PluginContext, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>> where Self: 'async_trait, 'life0: 'async_trait { ... }
}
Expand description

Extension point for SOF runtime event hooks.

Plugins are executed asynchronously by the plugin host worker, decoupled from ingest hot paths. Keep callbacks lightweight and use bounded work queues for any expensive downstream processing.

§Examples

use async_trait::async_trait;
use sof::framework::{ObserverPlugin, PluginConfig, TransactionEvent};

struct CriticalFlowPlugin;

#[async_trait]
impl ObserverPlugin for CriticalFlowPlugin {
    fn config(&self) -> PluginConfig {
        PluginConfig::new().with_inline_transaction()
    }

    async fn on_transaction(&self, event: &TransactionEvent) {
        let _signature = event.signature;
    }
}

Provided Methods§

fn name(&self) -> &'static str

Stable plugin identifier used in startup logs and diagnostics.

By default this uses core::any::type_name so simple plugins can skip boilerplate.

fn config(&self) -> PluginConfig

Returns static hook subscriptions requested by this plugin.

The host evaluates this once during construction and precomputes dispatch targets so the runtime does not need per-hook subscription lookups later.

fn setup<'life0, 'async_trait>( &'life0 self, _ctx: PluginContext, ) -> Pin<Box<dyn Future<Output = Result<(), PluginSetupError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called once before the runtime enters its main event loop.

fn on_raw_packet<'life0, 'async_trait>( &'life0 self, _event: RawPacketEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called for every UDP packet before shred parsing.

fn on_shred<'life0, 'async_trait>( &'life0 self, _event: ShredEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called for every packet that produced a valid parsed shred header.

fn on_dataset<'life0, 'async_trait>( &'life0 self, _event: DatasetEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called when a contiguous shred dataset is reconstructed.

fn accepts_transaction(&self, _event: &TransactionEvent) -> bool

Returns true when this plugin wants a specific decoded transaction callback.

This synchronous prefilter runs on the hot path before queueing the transaction hook. Use it to reject irrelevant transactions cheaply.

fn accepts_transaction_ref(&self, event: TransactionEventRef<'_>) -> bool

Borrowed transaction prefilter used on the dataset hot path.

Override this to avoid constructing an owned TransactionEvent for transactions that will be ignored anyway.

Plugins that only need borrowed fields should prefer this hook over Self::accepts_transaction.

fn transaction_interest(&self, event: &TransactionEvent) -> TransactionInterest

Returns transaction-interest priority for one decoded transaction callback.

The default preserves the historical API: accepted transactions are treated as critical and rejected transactions are ignored.

fn transaction_interest_ref( &self, event: TransactionEventRef<'_>, ) -> TransactionInterest

Borrowed transaction-interest classifier used on the dataset hot path.

Override this when classification can run directly on borrowed message data without first allocating an owned TransactionEvent.

Priority-sensitive plugins should implement this hook directly so the dataset hot path can classify traffic without allocating.

fn on_transaction<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called for each decoded transaction emitted from a completed contiguous data range.

By default this happens on the dataset-worker path. Plugins that request inline transaction delivery receive this hook from the completed-dataset boundary even when other dataset consumers still continue on the dataset-worker path.

fn on_transaction_batch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionBatchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called once per completed dataset with all decoded transactions in dataset order.

This hook is non-speculative. SOF invokes it only after a contiguous dataset is fully reconstructed and decoded, and before the runtime walks each transaction through the per-transaction plugin path.

fn on_transaction_view_batch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 TransactionViewBatchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called once per completed dataset with authoritative serialized transaction views.

This hook is non-speculative. SOF invokes it after the completed dataset payload is assembled and the transaction byte ranges are validated, but before full owned VersionedTransaction materialization. It is intended for low-latency completed-dataset consumers that can work directly on sanitized transaction views.

fn on_transaction_with_interest<'life0, 'life1, 'async_trait>( &'life0 self, event: &'life1 TransactionEvent, _interest: TransactionInterest, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called for each accepted decoded transaction with the already-computed routing lane.

Implement this when the plugin wants to avoid recomputing the same synchronous routing/classification work inside Self::on_transaction.

fn accepts_account_touch_ref(&self, _event: AccountTouchEventRef<'_>) -> bool

Borrowed account-touch prefilter used on the dataset hot path.

Override this to reject irrelevant account-touch callbacks before the runtime allocates owned account-key vectors.

fn on_account_touch<'life0, 'life1, 'async_trait>( &'life0 self, _event: &'life1 AccountTouchEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Called for each decoded transaction’s static touched-account set.

fn on_slot_status<'life0, 'async_trait>( &'life0 self, _event: SlotStatusEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called when local slot status transitions (processed/confirmed/finalized/orphaned).

fn on_reorg<'life0, 'async_trait>( &'life0 self, _event: ReorgEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called when local canonical tip switches to a different branch.

fn on_recent_blockhash<'life0, 'async_trait>( &'life0 self, _event: ObservedRecentBlockhashEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called when a newer observed recent blockhash is detected.

fn on_cluster_topology<'life0, 'async_trait>( &'life0 self, _event: ClusterTopologyEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called on low-frequency cluster topology diffs/snapshots (gossip-bootstrap mode).

fn on_leader_schedule<'life0, 'async_trait>( &'life0 self, _event: LeaderScheduleEvent, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called on event-driven leader-schedule diffs/snapshots.

fn shutdown<'life0, 'async_trait>( &'life0 self, _ctx: PluginContext, ) -> Pin<Box<dyn Future<Output = ()> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Called during runtime shutdown after ingest has stopped.

Implementors§