Skip to main content

ReactiveEngine

Struct ReactiveEngine 

Source
pub struct ReactiveEngine<S, N: Network = Ethereum> { /* private fields */ }
Expand description

Binds a ReactiveRuntime to an EventSubscriber for the common subscribe-ingest lifecycle.

The engine treats the runtime registry as the single source of truth for handler lifecycle: register_handler and unregister_handler update runtime routing and subscriber interests as one operation, keyed by the handler’s stable HandlerId. Registration is continuity-safe by default — once the runtime has journaled a canonical block, a newly registered handler is backfilled from that block, so a pool discovered in block N (say via a factory PoolCreated event) misses none of its own logs from N onward even though its live subscription starts later. Overlap between backfill and live delivery is absorbed by subscriber and runtime dedup.

Registration methods by intent:

MethodBackfill
register_handlerfrom the runtime’s last canonical block (live-only on a fresh runtime)
register_handler_with_backfillexplicit range or anchor (deep history)
register_handler_live_onlynone — future logs only

Unregistering a handler stops future subscription routing and runtime decode for that handler; it deliberately does not evict EvmCache state or undo runtime side effects. See unregister_handler for the complete teardown recipe.

The runtime and subscriber stay independently accessible through runtime_mut / subscriber_mut for advanced use. One caution: avoid calling EventSubscriber::register_interests (the full-replacement setup API) on an engine-managed subscriber — implementations may clear owner-scoped bookkeeping, after which per-handler unregistration no longer releases the handler’s transport subscriptions. To bootstrap the subscriber from a runtime that already has handlers, use sync_handler_interests, which registers one owner per handler instead of one unowned blob.

Implementations§

Source§

impl<S, N> ReactiveEngine<S, N>
where N: Network, S: EventSubscriber<N>,

Source

pub fn new(runtime: ReactiveRuntime<N>, subscriber: S) -> Self

Bind a runtime and subscriber.

Source

pub fn into_parts(self) -> (ReactiveRuntime<N>, S)

Split the engine into its runtime and subscriber parts.

Source

pub fn runtime(&self) -> &ReactiveRuntime<N>

Borrow the runtime.

Source

pub fn runtime_mut(&mut self) -> &mut ReactiveRuntime<N>

Mutably borrow the runtime.

Source

pub fn subscriber(&self) -> &S

Borrow the subscriber.

Source

pub fn subscriber_mut(&mut self) -> &mut S

Mutably borrow the subscriber.

Source

pub fn next_batch(&mut self) -> SubscriberNextBatch<'_, N>

Poll the subscriber for the next batch.

Source

pub fn ingest_batch( &mut self, cache: &mut EvmCache, batch: ReactiveInputBatch<N>, ) -> Result<ReactiveBatchReport<N>, ReactiveError>

Ingest one already-polled batch through the runtime (direct effects only; surfaced resync requests are reported, not executed).

Source

pub fn ingest_batch_with_resync( &mut self, cache: &mut EvmCache, batch: ReactiveInputBatch<N>, ) -> Result<ReactiveBatchReport<N>, ReactiveError>

Ingest one already-polled batch and execute the storage/account resyncs it surfaces, exactly like ReactiveRuntime::ingest_batch_with_resync.

Source

pub async fn next_ingest( &mut self, cache: &mut EvmCache, ) -> Result<Option<ReactiveBatchReport<N>>, ReactiveEngineError>

Poll the subscriber once and ingest the returned batch when present (direct effects only).

Source

pub async fn next_ingest_with_resync( &mut self, cache: &mut EvmCache, ) -> Result<Option<ReactiveBatchReport<N>>, ReactiveEngineError>

Poll the subscriber once and ingest the returned batch with resync execution — the loop shape for consumers that rely on coverage-gap repair (root-gate resyncs, handler-requested re-reads).

Source§

impl<S, N> ReactiveEngine<S, N>

Source

pub fn register_handler( &mut self, handler: Arc<dyn ReactiveHandler<N>>, ) -> Result<(), ReactiveEngineRegisterError>

Register a handler with both the runtime and subscriber, backfilling its log interests from the runtime’s last canonical block.

This is the continuity-safe default for mid-lifecycle registration: the runtime already knows how far it has processed the chain, so the new handler’s logs are fetched from that block forward and no discovery gap opens between “we decided to track this pool” and “its live subscription started”. On a runtime that has not journaled any canonical block yet (fresh start, or journal_depth 0) registration is live-only, matching pre-ingestion bootstrap. Use register_handler_with_backfill for deeper history or register_handler_live_only to opt out of backfill entirely.

If subscriber registration fails, the runtime registration is rolled back before the error is returned.

Source

pub fn register_handler_with_backfill( &mut self, handler: Arc<dyn ReactiveHandler<N>>, backfill: SubscriberBackfill, ) -> Result<(), ReactiveEngineRegisterError>

Register a handler and request an explicit owner-scoped log backfill for its interests (deep history / custom anchors).

If subscriber registration fails, the runtime registration is rolled back before the error is returned.

Source

pub fn register_handler_live_only( &mut self, handler: Arc<dyn ReactiveHandler<N>>, ) -> Result<(), ReactiveEngineRegisterError>

Register a handler without any log backfill — only logs delivered after its live subscription starts are routed to it.

If subscriber registration fails, the runtime registration is rolled back before the error is returned.

Source

pub fn sync_handler_interests(&mut self) -> Result<(), SubscriberError>

Register every handler currently in the runtime registry as a subscriber interest owner.

This is the bootstrap path for an engine built around a pre-populated runtime: each handler becomes its own owner (upsert semantics, so rerunning is safe and already-registered owners are refreshed in place). No backfill is requested — bootstrap happens before ingestion starts, so there is no processed position to be continuous with; use register_handler_with_backfill for handlers that need history. Owners are not removed by this call: use unregister_handler for lifecycle removal rather than mutating the runtime registry directly.

On error, owners already synced stay registered (upserts are independent); the call can simply be retried.

Source

pub fn unregister_handler( &mut self, id: &HandlerId, ) -> Option<Arc<dyn ReactiveHandler<N>>>

Unregister a handler from both the subscriber and runtime.

Subscriber interests are removed first so no new live records are routed to a handler after it has left the runtime registry. Returns the removed handler when the id was registered.

This is the routing/transport half of dropping an adapter. State the handler accumulated is deliberately left in place; the complete teardown for a pool or adapter that will not return is:

engine.unregister_handler(&id);
for address in handler_addresses {
    // stop root-gate eth_getProof probes for the account
    engine.runtime_mut().untrack_account(address);
    // drop its queued (unexecuted) repair work from the pending ledger
    engine.runtime_mut().cancel_pending_resyncs(address);
}
// optional: evict cached state via StateUpdate::purge / cache purge APIs

Health, metrics, the reorg journal, hooks, and freshness stamps are runtime-global and are never touched by handler removal.

Auto Trait Implementations§

§

impl<S, N = Ethereum> !Freeze for ReactiveEngine<S, N>

§

impl<S, N = Ethereum> !RefUnwindSafe for ReactiveEngine<S, N>

§

impl<S, N = Ethereum> !UnwindSafe for ReactiveEngine<S, N>

§

impl<S, N> Send for ReactiveEngine<S, N>
where S: Send,

§

impl<S, N> Sync for ReactiveEngine<S, N>
where S: Sync,

§

impl<S, N> Unpin for ReactiveEngine<S, N>
where S: Unpin, N: Unpin,

§

impl<S, N> UnsafeUnpin for ReactiveEngine<S, N>
where S: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more