use super::{Fetched, Remote, RemoteStatus};
use crate::error::Error;
#[derive(Clone, Copy)]
pub struct RemoteSink {
remote: &'static Remote,
generation: u64,
reload: fn() -> Result<(), Error>,
name: &'static str,
}
impl RemoteSink {
#[doc(hidden)]
#[must_use]
pub fn new(
remote: &'static Remote,
reload: fn() -> Result<(), Error>,
name: &'static str,
) -> Self {
Self {
remote,
generation: remote.generation(),
reload,
name,
}
}
#[must_use]
pub fn status(&self) -> RemoteStatus {
self.remote.status()
}
pub fn failed(&self, error: &Error) {
self.remote.record_fetch_failure(error, self.generation);
}
pub fn apply(&self, document: Fetched) -> Result<(), Error> {
self.remote.install_if(self.generation, document)?;
let outcome = (self.reload)();
if self.remote.generation() != self.generation {
let _ = (self.reload)();
let error = Error::new(
crate::ErrorKind::Backend,
"the remote source this sink was created for was replaced \
while its delivery reloaded; the replacement's state was \
restored — stop the old watch loop and take a fresh sink \
from `remote_sink()`",
);
crate::__log_remote_failure(self.name, &error);
return Err(error);
}
match outcome {
Ok(()) => {
crate::__log_remote_reload(self.name, None);
Ok(())
}
Err(error) => {
crate::__log_remote_failure(self.name, &error);
Err(error)
}
}
}
}
impl std::fmt::Debug for RemoteSink {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RemoteSink")
.field("config", &self.name)
.field("generation", &self.generation)
.finish_non_exhaustive()
}
}