pub trait BackendServer:
Debug
+ Send
+ Sync {
// Required methods
fn add(&self, name: &str, dev: Arc<dyn BackendDev>) -> Result<Arc<str>>;
fn remove(&self, name: &str) -> bool;
fn host(&self) -> Arc<str> ⓘ;
fn port(&self) -> u16;
fn version(&self) -> i32;
fn stop(&self);
fn wait(&self) -> BoxFuture<'_, ()>;
// Provided methods
fn zmq_event_subscription_change(
&self,
_args: Spectrum<str>,
) -> BoxFuture<'_, Result<(Spectrum<i32>, Spectrum<str>)>> { ... }
fn event_confirm_subscription(
&self,
_args: Spectrum<str>,
) -> BoxFuture<'_, Result<()>> { ... }
}Expand description
The backend for a server that is served, from the moment Backend::serve hands it
over until it is stopped, see Self::stop, or dropped.
Nothing here waits but Self::wait: adding, removing a device and stopping are quick
and never block, so they are called from anywhere, a request of one of the devices of
the backend included. What they ask for happens at some point after, a device that was
removed still answering the requests it was answering, for instance.
A backend holds the devices it serves, strongly, from Self::add, and, once they
were removed or the backend stopped, until their requests in flight are answered, and
never beyond Self::wait: once it resolves, no Arc to any device is left
anywhere in the backend. This is what lets the owner of a device rely on the device
being dropped with the last reference it has.
§Dropping
Dropping the last Arc to a backend server drops everything of it at once, with no
side effect: every device it serves is let go of, and every request in flight is
cancelled, its future dropped and nothing answered. A server that is to end properly is
therefore stopped and waited for before it is dropped.
Required Methods§
Sourcefn add(&self, name: &str, dev: Arc<dyn BackendDev>) -> Result<Arc<str>>
fn add(&self, name: &str, dev: Arc<dyn BackendDev>) -> Result<Arc<str>>
Add a device to be served, giving back its ITR, which it is reachable at from then on or shortly after. The name of the device is given with the device so the server doesn’t have to call the name() function on it. This is quick and never blocks, see the trait documentation.
Device names are not case sensitive: a backend lowercases the name as soon as it is
given, which every later lookup of the device, from Self::remove to the requests
of the clients, then relies on.
The server might return any error, but the error NotHandled should be ignored.
Sourcefn remove(&self, name: &str) -> bool
fn remove(&self, name: &str) -> bool
Stop serving the device of that name, giving back whether one was being served. No new request reaches it from the call on, or shortly after, and the ones it was answering are still answered. This is quick and never blocks, see the trait documentation.
The device itself is not given back: the backend drops what it was holding of it once its requests are answered, which is what makes it stop being reachable.
Sourcefn version(&self) -> i32
fn version(&self) -> i32
The version of the protocol the devices are served with, which is what a client is told of a device in its info and what the database is told when it is exported.
Sourcefn stop(&self)
fn stop(&self)
Stop serving, which nothing undoes: a backend that was stopped is one no client
reaches again, whatever is added to it afterward. Every device is removed, all at
once, as Self::remove does: no new request is taken, and the ones being answered
are.
This does not wait for anything, and can therefore be called from anywhere,
including from a request of one of its devices; see Self::wait for that.
Sourcefn wait(&self) -> BoxFuture<'_, ()>
fn wait(&self) -> BoxFuture<'_, ()>
Resolve once this backend was stopped, see Self::stop, and holds nothing of any
of its devices anymore, see the trait documentation, after which dropping it is
dropping nothing of them.
This waits until every request in flight is answered, so it may not be awaited from a future the backend is driving, that is from a request of one of its devices: at best that request is left hanging, at worst it waits for itself. Waiting is all it does, the future it gives back never blocking the thread polling it, as for every future of a backend.
Provided Methods§
Sourcefn zmq_event_subscription_change(
&self,
_args: Spectrum<str>,
) -> BoxFuture<'_, Result<(Spectrum<i32>, Spectrum<str>)>>
fn zmq_event_subscription_change( &self, _args: Spectrum<str>, ) -> BoxFuture<'_, Result<(Spectrum<i32>, Spectrum<str>)>>
Answer the ZmqEventSubscriptionChange command of the admin device, which a client
sends to have an event published and to be told where it is published. The
argument and the result are those of the command, as a client sends and expects
them.
A backend that publishes no event this way answers that it is not implemented, which is what this does by default.
Sourcefn event_confirm_subscription(
&self,
_args: Spectrum<str>,
) -> BoxFuture<'_, Result<()>>
fn event_confirm_subscription( &self, _args: Spectrum<str>, ) -> BoxFuture<'_, Result<()>>
Answer the EventConfirmSubscription command of the admin device, which a client
sends periodically to keep the events it subscribed to published. The argument is
that of the command, a list of device name, attribute name and event name triplets.
A backend that publishes no event this way answers that it is not implemented, which is what this does by default.
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".