pub struct PvaServer { /* private fields */ }Expand description
High-level PVAccess server.
Built via PvaServer::builder() with typed record constructors,
.db_file() loading, .on_put() / .scan() callbacks, and a
simple .run() to start serving.
let server = PvaServer::builder()
.ai("SIM:TEMP", 22.5)
.ao("SIM:SP", 25.0)
.build();
// Read/write PVs from another task:
let store = server.store();
store.set_value("SIM:TEMP", ScalarValue::F64(23.1)).await;
server.run().await?;Implementations§
Source§impl PvaServer
impl PvaServer
Sourcepub fn builder() -> PvaServerBuilder
pub fn builder() -> PvaServerBuilder
Create a builder for configuring a PvaServer.
Sourcepub fn store(&self) -> &Arc<SimplePvStore> ⓘ
pub fn store(&self) -> &Arc<SimplePvStore> ⓘ
Get a reference to the underlying store for runtime get/put.
Sourcepub fn events(&self) -> &Arc<Events> ⓘ
pub fn events(&self) -> &Arc<Events> ⓘ
The server’s event registry — register sinks or post events.
Sourcepub async fn post_event(&self, event: &str)
pub async fn post_event(&self, event: &str)
Post a named event.
Async because sinks are awaited inline: when this returns, every sink
has finished — records on that event have processed — and handlers
are queued, not necessarily run. Making the caller .await is what
buys the guarantee; a sync wrapper that spawned and returned would
silently drop it.
Sourcepub async fn run_start_hooks(&self) -> Result<(), String>
pub async fn run_start_hooks(&self) -> Result<(), String>
Run every on_start hook to completion, in registration order.
Returns Err naming the hook and carrying the panic message if one
panics — including any label the hook panicked with (Python source
hooks panic with on_start hook for source '<label>' raised: ...).
Also installs the monitor registry onto the store before any hook
runs (idempotently — SimplePvStore::set_registry is safe to call
more than once), so a hook that writes to the store notifies
subscribed monitors, and a hook that reads the registry off the
store never sees None. This must happen here rather than only in
serve_after_start_hooks, since run_start_hooks can be — and, via
Python’s start_background, is — called on its own ahead of it.
Sourcepub async fn pv<T: PvScalar>(&self, name: &str) -> Result<Pv<T>, PvError>
pub async fn pv<T: PvScalar>(&self, name: &str) -> Result<Pv<T>, PvError>
Mint a typed handle to any record in this server’s store — the
pre-run() counterpart of RunningServer::pv.
Sourcepub async fn array_pv(&self, name: &str) -> Result<PvArray, PvError>
pub async fn array_pv(&self, name: &str) -> Result<PvArray, PvError>
Mint an array handle to any record in this server’s store — the
pre-run() counterpart of RunningServer::array_pv.
Sourcepub fn add_source(
&mut self,
label: impl Into<String>,
order: i32,
source: Arc<dyn Source>,
)
pub fn add_source( &mut self, label: impl Into<String>, order: i32, source: Arc<dyn Source>, )
Register an additional Source after building the server.
This is useful when the source needs a reference to the store
(which is only available after .build()).
let server = PvaServer::builder().ai("X", 0.0).build();
let store = server.store().clone();
server.add_source("agg", 10, Arc::new(MyAggSource::new(store)));
server.run().await?;Sourcepub fn set_monitor_registry(&mut self, registry: Arc<MonitorRegistry>)
pub fn set_monitor_registry(&mut self, registry: Arc<MonitorRegistry>)
Pre-supply the MonitorRegistry that Self::run will use.
This lets external code (for example Python Source adapters)
hold onto the registry and publish monitor updates to subscribed
PVAccess clients from outside run().
Must be called before the registry has been resolved by any other
path (monitor_registry(), run_start_hooks(), or
serve_after_start_hooks()) — in normal usage this is always right
after build(), before any of those run. If the registry was
already resolved, this is a no-op: the earlier instance wins.
Sourcepub fn monitor_registry(&mut self) -> Arc<MonitorRegistry> ⓘ
pub fn monitor_registry(&mut self) -> Arc<MonitorRegistry> ⓘ
Get a shared handle to the MonitorRegistry that will be used
when Self::run starts. Creates (and stores) a new registry
on first call so external code can register before run.
Sourcepub async fn run(self) -> Result<(), Box<dyn Error>>
pub async fn run(self) -> Result<(), Box<dyn Error>>
Start the PVA server (UDP search + TCP handler + beacon + scan tasks).
This blocks until the server is shut down or an error occurs.
Sourcepub async fn serve_after_start_hooks(self) -> Result<(), Box<dyn Error>>
pub async fn serve_after_start_hooks(self) -> Result<(), Box<dyn Error>>
Continue startup on the assumption that run_start_hooks() has
already completed successfully.
Builds the source registry, spawns scan tasks, starts the event
dispatcher, and binds/accepts connections — i.e. everything run()
does except the hook phase. Exists so a caller that needs to surface
an on_start failure synchronously (e.g. Python’s
start_background, which must raise before returning rather than
only logging from a background thread) can run the hooks itself,
check the result, and only then hand the server off to a background
task — without running the hooks a second time.
Calling this without having run the start hooks first silently skips
them; callers that need the hooks-first guarantee should use run()
or call run_start_hooks() first themselves.
Source§impl PvaServer
impl PvaServer
Sourcepub fn serve(pvs: impl IntoIterator<Item = impl Into<AnyPv>>) -> ServeBuilder
pub fn serve(pvs: impl IntoIterator<Item = impl Into<AnyPv>>) -> ServeBuilder
Serve a collection of typed PV handles. Shorthand entry point for the
handle-based API; combine with .db_file(), .source(), etc.