Skip to main content

ReplayDriver

Struct ReplayDriver 

Source
pub struct ReplayDriver { /* private fields */ }
Expand description

Serves a captured (time, PV) trace through the real Driver trait, for validating that a live MrftEngine run reproduces a golden-master trace’s result when driven through the actual async abstraction – not just when fed the trace directly, as core-replay-harness already does at the pure-engine level.

Reading the configured PV tag returns the next unconsumed sample’s PV value, with its real recorded time in TagValue.timestamp. This is the one Driver implementation in this crate where that field is genuinely meaningful rather than a diagnostic-only extra: crate::types::TagValue’s own doc comment is clear that a live driver’s timestamp must never become “the tick time the tuning engine itself runs on, which comes from the caller’s own polling clock instead” – true and load-bearing for OpcDaDriver/SimulatorDriver, whose reported (or absent) timestamps cannot be trusted to reconstruct a control loop’s real tick cadence. ReplayDriver is a deliberate, narrow exception to that rule, not a violation of it: it is not a live driver at all, its entire purpose is exact historical replay, and the recorded time is the tick time a validation test needs – reading it straight back out of the trait boundary is simpler and less redundant than threading the same value through some separate side channel the test would otherwise have to keep in lockstep with this driver’s own internal cursor.

Reading the configured MV tag returns the last written value (or the seeded initial MV before any write), matching crate::SimulatorDriver’s convention exactly. Running a PV read past the last recorded sample is DriverError::Operation (wrapping ReplayTraceExhausted) rather than panicking or silently repeating/holding the last value, since either of those would let a real regression (the engine failing to complete) masquerade as a passing test.

Uses std::sync::Mutex, matching crate::SimulatorDriver: every operation here is synchronous index/vec bookkeeping with no .await point in the critical section.

Implementations§

Source§

impl ReplayDriver

Source

pub fn new( pv_tag: impl Into<TagId>, mv_tag: impl Into<TagId>, samples: Vec<ReplaySample>, initial_mv: f32, ) -> ReplayDriver

Builds a replay driver from an already-parsed sample sequence. initial_mv is what the MV tag reads as before the first write – mirroring crate::SimulatorDriver::new’s initial_mv parameter, and matching the fact that a real trace’s MV convention (see crates/bhtune-core/tests/golden_replay.rs’s FixtureInitial::mv_ini) is likewise supplied out of band from the tick sequence itself.

Source

pub fn from_fixture_json( pv_tag: impl Into<TagId>, mv_tag: impl Into<TagId>, json: &str, initial_mv: f32, ) -> DriverResult<ReplayDriver>

Parses a golden-master fixture JSON document’s ticks[].time/ticks[].pv fields (see [FixtureFile]) into the sample sequence ReplayDriver::new expects, so a validation test can point this driver directly at the same fixture file core-replay-harness already validates against (tests/golden/fixtures/*.json) rather than hand-transcribing the tick sequence a second time. A parse failure is DriverError::Operation, matching this crate’s error-model doc comment’s own forward-looking note that golden-trace parse errors belong there.

Source

pub fn writes(&self) -> Vec<RecordedWrite>

Every MV write observed so far, in call order – for a validation test to compare against a golden fixture’s own expected per-tick MV sequence.

Source

pub fn remaining(&self) -> usize

How many configured samples have not yet been consumed by a PV read.

Trait Implementations§

Source§

impl Debug for ReplayDriver

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Driver for ReplayDriver

Source§

fn read<'life0, 'life1, 'async_trait>( &'life0 self, tags: &'life1 [TagId], ) -> Pin<Box<dyn Future<Output = DriverResult<Vec<TagValue>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Reads the current value of every tag in tags, in one batched call where the driver supports it (a single OPC DA Read RPC for all of them, rather than one round trip per tag). Returns exactly one TagValue per requested tag, in the same order as tags. Read more
Source§

fn write<'life0, 'life1, 'async_trait>( &'life0 self, tag: &'life1 TagId, value: TagWrite, ) -> Pin<Box<dyn Future<Output = DriverResult<WriteOutcome>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Writes value to tag. Read more
Source§

fn capabilities<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = DriverResult<DriverCapabilities>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Reports the namespace capabilities of this driver/server pair.
Source§

fn browse<'life0, 'async_trait>( &'life0 self, _request: BrowsePageRequest, ) -> Pin<Box<dyn Future<Output = DriverResult<BrowsePage>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Lists one bounded page of immediate children. Navigation uses opaque session, node, and continuation values returned by the driver; callers must not infer hierarchy by parsing punctuation in an ItemID.
Source§

fn close_browse_session<'life0, 'life1, 'async_trait>( &'life0 self, _session_id: &'life1 str, ) -> Pin<Box<dyn Future<Output = DriverResult<()>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait,

Releases a server-side browse session.
Source§

fn search<'life0, 'async_trait>( &'life0 self, _request: SearchRequest, ) -> Pin<Box<dyn Future<Output = DriverResult<Vec<SearchEvent>>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Collects a bounded namespace search. Drivers that support progressive search may expose a richer stream through their concrete type; this method is the portable trait surface.
Source§

fn search_index_status<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Reports the gateway-owned persistent namespace-index status.
Source§

fn refresh_search_index<'life0, 'async_trait>( &'life0 self, _force: bool, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Starts or coalesces a persistent namespace-index refresh.
Source§

fn control_search_index<'life0, 'async_trait>( &'life0 self, _action: SearchIndexControlAction, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Pauses, resumes, or cancels a persistent namespace-index build.
Source§

fn set_search_index_auto_refresh<'life0, 'async_trait>( &'life0 self, _enabled: bool, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Enables or disables future automatic refreshes for this server’s index.
Source§

fn delete_search_index<'life0, 'async_trait>( &'life0 self, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexStatus>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Deletes this server’s persistent namespace index and enrollment.
Source§

fn search_index<'life0, 'async_trait>( &'life0 self, _request: SearchIndexRequest, ) -> Pin<Box<dyn Future<Output = DriverResult<SearchIndexResponse>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait,

Queries the gateway-owned persistent namespace index.

Auto Trait Implementations§

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

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

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

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.

§

impl<T> IntoRequest<T> for T

§

fn into_request(self) -> Request<T>

Wrap the input message T in a tonic::Request
§

impl<L> LayerExt<L> for L

§

fn named_layer<S>(&self, service: S) -> Layered<<L as Layer<S>>::Service, S>
where L: Layer<S>,

Applies the layer to a service and wraps it in [Layered].
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.
§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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