use crate::session::admin_request::AdminRequest;
use crate::session::error::{SendError, SendOutcome, SetNextTargetSeqNumError};
use crate::session::session_ref::OutboundRequest;
use crate::session::{InternalSessionRef, SessionInfo};
use std::num::NonZeroU64;
use tokio::sync::{mpsc, oneshot};
#[derive(Clone, Debug)]
pub struct SessionHandle<Outbound> {
outbound_message_sender: mpsc::Sender<OutboundRequest<Outbound>>,
admin_request_sender: mpsc::Sender<AdminRequest>,
}
impl<Outbound> SessionHandle<Outbound> {
pub async fn get_session_info(&self) -> Result<SessionInfo, SendError> {
let (sender, receiver) = oneshot::channel::<SessionInfo>();
self.admin_request_sender
.send(AdminRequest::RequestSessionInfo(sender))
.await?;
Ok(receiver.await?)
}
pub async fn send(&self, msg: Outbound) -> Result<SendOutcome, SendError> {
let (tx, rx) = oneshot::channel();
let request = OutboundRequest {
message: msg,
confirm: Some(tx),
};
self.outbound_message_sender.send(request).await?;
rx.await?
}
pub async fn send_forget(&self, msg: Outbound) -> Result<(), SendError> {
let request = OutboundRequest {
message: msg,
confirm: None,
};
self.outbound_message_sender.send(request).await?;
Ok(())
}
pub async fn shutdown(&self, reconnect: bool) -> Result<(), SendError> {
self.admin_request_sender
.send(AdminRequest::InitiateGracefulShutdown { reconnect })
.await?;
Ok(())
}
pub async fn request_reset_on_next_logon(&self) -> Result<(), SendError> {
self.admin_request_sender
.send(AdminRequest::ResetSequenceNumbersOnNextLogon)
.await?;
Ok(())
}
pub async fn set_next_target_seq_num(
&self,
seq_num: NonZeroU64,
) -> Result<(), SetNextTargetSeqNumError> {
let (responder, receiver) = oneshot::channel();
self.admin_request_sender
.send(AdminRequest::SetNextTargetSeqNum { seq_num, responder })
.await
.map_err(|_| SetNextTargetSeqNumError::Send(SendError::SessionGone))?;
receiver
.await
.map_err(|_| SetNextTargetSeqNumError::Send(SendError::SessionGone))?
}
}
impl<M> From<InternalSessionRef<M>> for SessionHandle<M> {
fn from(session_ref: InternalSessionRef<M>) -> Self {
Self {
outbound_message_sender: session_ref.outbound_message_sender.clone(),
admin_request_sender: session_ref.admin_request_sender.clone(),
}
}
}