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
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
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,
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,
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,
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,
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
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
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
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
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,
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,
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,
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,
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
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,
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,
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,
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,
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,
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,
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.