use std::{collections::HashMap, path::PathBuf};
use stdweb::{self, unstable::TryInto, Reference, Value};
use Process;
pub fn initialize() -> Option<&'static Reference> {
static mut CLUSTER: Option<Reference> = None;
if unsafe { CLUSTER.is_none() } {
unsafe {
CLUSTER = js! {
return @{ super::js_private() }.cluster = require("cluster");
}.into_reference()
};
}
unsafe { CLUSTER.as_ref() }
}
pub fn cluster() -> &'static Reference {
initialize().expect("cluster module could not be loaded")
}
pub fn fork() -> Worker {
(js! {
return @{cluster()}.fork();
}).try_into()
.expect("fork() did not return a Worker!")
}
pub fn is_master() -> bool {
(js! {
return @{cluster()}.isMaster;
}).try_into()
.expect("isMaster was not bool!")
}
pub fn is_worker() -> bool {
(js! {
return @{cluster()}.isWorker;
}).try_into()
.expect("isWorker was not bool!")
}
pub fn worker() -> Option<Worker> {
(js! {
return @{cluster()}.worker;
}).try_into()
.ok()
}
#[derive(Default)]
pub struct ClusterSettingsBuilder {
settings: HashMap<&'static str, Value>,
}
impl ClusterSettingsBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn exec(mut self, exec: PathBuf) -> Self {
self.settings.insert(
"exec",
js! { return @{exec.into_os_string().into_string().unwrap()}; },
);
self
}
pub fn build(&self) -> ClusterSettings {
(js! {
return @{&self.settings};
}).try_into()
.unwrap()
}
}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Object")]
pub struct ClusterSettings(Reference);
pub fn setup_master(settings: ClusterSettings) {
js! {
@(no_return)
@{cluster()}.setupMaster(@{settings});
}
}
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "RUST_NODEJS_PRIVATE.cluster.Worker")]
pub struct Worker(Reference);
impl Worker {
pub fn process(&self) -> Process {
(js! {
return @{&self}.process;
}).try_into()
.expect("Worker did not have a process member!")
}
pub fn disconnect(&self) {
js! {
@{&self}.disconnect();
};
}
pub fn on_exit<F: 'static + FnOnce(i32, Option<&str>) -> ()>(&self, callback: F) {
let on_exit_callback = move |code: stdweb::Value, signal: stdweb::Value| {
let code = code.try_into().unwrap();
let signal = (&signal).try_into().ok();
callback(code, signal);
};
js! {
@{&self.0}.on("exit", (code, signal) => {
let on_exit_callback = @{stdweb::Once(on_exit_callback)};
on_exit_callback(code, signal);
});
}
}
}