use crate::debugger;
use crate::error::{NodeError, NodeReason};
use crate::{relay::WorkerRelay, Context, NodeMessage};
use ockam_core::compat::sync::Arc;
use ockam_core::{
errcode::{Kind, Origin},
Address, Error, IncomingAccessControl, Mailboxes, Message, OutgoingAccessControl, Result,
Worker,
};
pub struct WorkerBuilder<W> {
mailboxes: Mailboxes,
worker: W,
}
impl<M, W> WorkerBuilder<W>
where
M: Message + Send + 'static,
W: Worker<Context = Context, Message = M>,
{
pub fn with_access_control(
incoming_access_control: Arc<dyn IncomingAccessControl>,
outgoing_access_control: Arc<dyn OutgoingAccessControl>,
address: impl Into<Address>,
worker: W,
) -> Self {
let mailboxes = Mailboxes::main(
address.into(),
incoming_access_control,
outgoing_access_control,
);
Self { mailboxes, worker }
}
pub fn with_mailboxes(mailboxes: Mailboxes, worker: W) -> Self {
Self { mailboxes, worker }
}
#[inline]
pub async fn start(self, context: &Context) -> Result<Address> {
info!(
"Initializing ockam worker '{}' with access control in:{:?} out:{:?}",
self.mailboxes.main_address(),
self.mailboxes.main_mailbox().incoming_access_control(),
self.mailboxes.main_mailbox().outgoing_access_control(),
);
let mailboxes = self.mailboxes;
let addresses = mailboxes.addresses();
let main_address = mailboxes.main_address().clone();
let (ctx, sender, ctrl_rx) = Context::new(
context.runtime().clone(),
context.sender().clone(),
mailboxes,
None,
);
debugger::log_inherit_context("WORKER", context, &ctx);
WorkerRelay::<W, M>::init(context.runtime(), self.worker, ctx, ctrl_rx);
let (msg, mut rx) =
NodeMessage::start_worker(addresses, sender, false, context.mailbox_count());
context
.sender()
.send(msg)
.await
.map_err(|e| Error::new(Origin::Node, Kind::Invalid, e))?;
rx.recv()
.await
.ok_or_else(|| NodeError::NodeState(NodeReason::Unknown).internal())??;
Ok(main_address)
}
}