use std::sync::{Arc, mpsc};
use crate::channel::ChannelMode;
use crate::conversation::participant::ConsumptionPermit;
use crate::conversation::{
ConversationActor, ConversationSupervisor, CrashPolicy, EchoBehaviour, ParticipantBehaviour,
ParticipantPid,
};
use crate::envelope::Envelope;
use crate::error::LiminalError;
#[derive(Debug)]
struct NoReply;
impl ParticipantBehaviour for NoReply {
fn process(&self, _: &Envelope) -> Option<Envelope> {
None
}
}
pub struct ControlledConsumer {
pub(crate) owner: ConversationActor,
pub(crate) pid: ParticipantPid,
pub(crate) permit: ConsumptionPermit,
pub(crate) parked: mpsc::Receiver<()>,
}
impl ControlledConsumer {
pub(crate) fn new(supervisor: &ConversationSupervisor) -> Result<Self, LiminalError> {
Self::with_behaviour(supervisor, Arc::new(NoReply))
}
pub(crate) fn echo(supervisor: &ConversationSupervisor) -> Result<Self, LiminalError> {
Self::with_behaviour(supervisor, Arc::new(EchoBehaviour))
}
fn with_behaviour(
supervisor: &ConversationSupervisor,
behaviour: Arc<dyn ParticipantBehaviour>,
) -> Result<Self, LiminalError> {
let (owner, pid) = supervisor.spawn_with_participant(
behaviour,
None,
ChannelMode::Ephemeral,
CrashPolicy::RouteToNext,
)?;
let (permit, parked) = supervisor.hold_participant_consumption(pid)?;
Ok(Self {
owner,
pid,
permit,
parked,
})
}
}
impl Drop for ControlledConsumer {
fn drop(&mut self) {
self.owner.finalize();
}
}