mod delivery;
use std::sync::Arc;
use crate::dispatch::DeferredResponseSeed;
use crate::server::SessionHandle;
use crate::session_view::SessionStateView;
use rocketmq_runtime::TaskGroup;
use delivery::LocalResponseSenderState;
pub(crate) use delivery::ResponseDeliveryContext;
pub(crate) use delivery::ResponseTransportDropHandle;
#[derive(Clone)]
pub(crate) struct LocalResponseSink {
state: Arc<LocalResponseSenderState>,
}
impl Drop for LocalResponseSink {
fn drop(&mut self) {
if Arc::strong_count(&self.state) == 1 {
self.state.close_last_sender();
}
}
}
#[derive(Clone)]
pub(crate) enum ResponseSink {
Network(Arc<SessionHandle>),
Local(LocalResponseSink),
}
impl ResponseSink {
pub(crate) fn is_local_owner(&self, session: &SessionStateView, task_group: &TaskGroup) -> bool {
matches!(
self,
Self::Local(LocalResponseSink { state })
if state.control().same_lifecycle_owner(session, task_group)
)
}
pub(crate) fn local_deferred_seed_with_resume(
&self,
telemetry: crate::telemetry::TransportTelemetry,
session: &crate::session_view::SessionView,
task_group: &TaskGroup,
ordering: crate::request_ordering::RequestOrdering,
class: crate::admission::AdmissionClass,
executor: crate::session_executor::DeferredResumeExecutor,
) -> Option<DeferredResponseSeed> {
if !matches!(session, crate::session_view::SessionView::Embedded { .. })
|| !self.is_local_owner(session.state(), task_group)
{
return None;
}
Some(
DeferredResponseSeed::new(self.clone(), telemetry, session.id(), self.local_control()?.clone())
.with_resume_context(ordering, class, executor),
)
}
fn local_control(&self) -> Option<&crate::dispatch::RequestControlView> {
match self {
Self::Local(LocalResponseSink { state }) => Some(state.control()),
Self::Network(_) => None,
}
}
pub(crate) fn is_canonical_network_owner(&self, session: &SessionHandle) -> bool {
matches!(
self,
Self::Network(owner)
if owner.same_canonical_owner(session)
&& owner
.response_context()
.is_some_and(|context| context.same_lifecycle_owner(session))
)
}
pub(crate) fn network_deferred_seed_with_resume(
&self,
session: &SessionHandle,
ordering: crate::request_ordering::RequestOrdering,
class: crate::admission::AdmissionClass,
executor: crate::session_executor::DeferredResumeExecutor,
) -> Option<DeferredResponseSeed> {
if !self.is_canonical_network_owner(session) {
return None;
}
let Self::Network(owner) = self else {
return None;
};
let context = owner.response_context()?;
Some(
DeferredResponseSeed::new(
self.clone(),
session.connection().telemetry(),
session.session_view().id(),
context.control().clone(),
)
.with_resume_context(ordering, class, executor),
)
}
#[cfg(test)]
pub(crate) fn network_deferred_seed(&self, session: &SessionHandle) -> Option<DeferredResponseSeed> {
if !self.is_canonical_network_owner(session) {
return None;
}
let Self::Network(owner) = self else {
return None;
};
let context = owner.response_context()?;
Some(DeferredResponseSeed::new(
self.clone(),
session.connection().telemetry(),
session.session_view().id(),
context.control().clone(),
))
}
#[cfg(test)]
pub(crate) fn deferred_seed_for_test(
&self,
telemetry: crate::telemetry::TransportTelemetry,
session_id: crate::session_view::SessionId,
control: crate::dispatch::RequestControlView,
) -> DeferredResponseSeed {
DeferredResponseSeed::new(self.clone(), telemetry, session_id, control)
}
}