use crate::messaging::{AsyncSendError, CanSend, MessageWithCallback};
use near_o11y::{WithSpanContext, WithSpanContextExt};
impl<M, A> CanSend<M> for actix::Addr<A>
where
M: actix::Message + Send + 'static,
M::Result: Send,
A: actix::Actor + actix::Handler<M>,
A::Context: actix::dev::ToEnvelope<A, M>,
{
fn send(&self, message: M) {
match self.try_send(message) {
Ok(_) => {}
Err(err) => match err {
actix::dev::SendError::Full(message) => {
self.do_send(message);
}
actix::dev::SendError::Closed(_) => {
near_o11y::tracing::warn!(
"Tried to send {} message to closed actor",
std::any::type_name::<M>()
);
}
},
}
}
}
pub type ActixResult<T> = <T as actix::Message>::Result;
impl<M, A> CanSend<MessageWithCallback<M, M::Result>> for actix::Addr<A>
where
M: actix::Message + Send + 'static,
M::Result: Send,
A: actix::Actor + actix::Handler<M>,
A::Context: actix::dev::ToEnvelope<A, M>,
{
fn send(&self, message: MessageWithCallback<M, M::Result>) {
let MessageWithCallback { message, callback: responder } = message;
let future = self.send(message);
actix::spawn(async move {
match future.await {
Ok(result) => responder(Ok(result)),
Err(actix::MailboxError::Closed) => responder(Err(AsyncSendError::Closed)),
Err(actix::MailboxError::Timeout) => responder(Err(AsyncSendError::Timeout)),
}
});
}
}
pub struct AddrWithAutoSpanContext<T: actix::Actor> {
inner: actix::Addr<T>,
}
impl<T: actix::Actor> Clone for AddrWithAutoSpanContext<T> {
fn clone(&self) -> Self {
Self { inner: self.inner.clone() }
}
}
pub trait AddrWithAutoSpanContextExt<T: actix::Actor> {
fn with_auto_span_context(self) -> AddrWithAutoSpanContext<T>;
}
impl<T: actix::Actor> AddrWithAutoSpanContextExt<T> for actix::Addr<T> {
fn with_auto_span_context(self) -> AddrWithAutoSpanContext<T> {
AddrWithAutoSpanContext { inner: self }
}
}
impl<M, S> CanSend<M> for AddrWithAutoSpanContext<S>
where
M: actix::Message + 'static,
S: actix::Actor,
actix::Addr<S>: CanSend<WithSpanContext<M>>,
{
fn send(&self, message: M) {
CanSend::send(&self.inner, message.with_span_context());
}
}
impl<M, S> CanSend<MessageWithCallback<M, M::Result>> for AddrWithAutoSpanContext<S>
where
M: actix::Message + Send + 'static,
M::Result: Send,
S: actix::Actor,
actix::Addr<S>: CanSend<MessageWithCallback<WithSpanContext<M>, M::Result>>,
{
fn send(&self, message: MessageWithCallback<M, M::Result>) {
let MessageWithCallback { message, callback: responder } = message;
CanSend::send(
&self.inner,
MessageWithCallback { message: message.with_span_context(), callback: responder },
);
}
}