✨ valkey task distribution
This commit is contained in:
parent
e827faaa3f
commit
f381f30e27
7 changed files with 866 additions and 26 deletions
|
@ -5,10 +5,13 @@ use syn::{FnArg, Ident, ItemFn, Pat, ReturnType, Type, parse_macro_input};
|
|||
/// This macro turns this function into a worker.
|
||||
///
|
||||
/// This will upgrade the function and generate a few ones (`fn` is a placeholder for the functions name):
|
||||
/// - `fn()` - This function will be exactly the same as the original but it will be computed by a worker.
|
||||
/// - `fn_init(&ServiceManager) -> ServiceManager` - This function registers a worker thread on a `ServiceManager`.
|
||||
/// - `fn_shutdown()` - This function issues a shutdown request.
|
||||
/// - `fn_init_scoped(&ServiceManager) -> (ServiceManager, fn_Scoped)` - This function registers a worker thread on a `ServiceManager` and returns a scoped struct. You can call the underlying function with `.call()` on the struct and it will automatically shutdown any workers if it gets out of scope.
|
||||
/// - `fn()` - Behaves exactly the same as the original but it will be computed by a worker.
|
||||
/// - `fn_init(ServiceManager) -> ServiceManager` - Registers worker threads on a `ServiceManager`.
|
||||
/// - `fn_shutdown()` - Issue a shutdown request.
|
||||
/// - `fn_init_scoped(ServiceManager) -> (ServiceManager, fn_Scoped)` - Registers worker threads on a `ServiceManager` and return a scoped struct. You can call the underlying function with `.call()` on the struct and it will automatically shutdown any workers if it gets out of scope.
|
||||
/// - `fn_init_union(ServiceManager) -> ServiceManager` - Register worker threads and work in a union using Valkey.
|
||||
/// - `fn_init_union_scoped(ServiceManager) -> ServiceManager` - Register worker threads and work in a union using Valkey and return a scoped struct.
|
||||
/// - `fn_register_union()` - Register the worker in a union setup without starting local worker threads.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```ignore
|
||||
|
@ -81,9 +84,12 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let wrapper_fn = format_ident!("{}_wrapper", fn_name);
|
||||
let worker_fn = format_ident!("{}_worker", fn_name);
|
||||
let init_fn = format_ident!("{}_init", fn_name);
|
||||
let init_fn_union = format_ident!("{}_init_union", fn_name);
|
||||
let init_fn_scoped = format_ident!("{}_init_scoped", fn_name);
|
||||
let init_fn_scoped_union = format_ident!("{}_init_union_scoped", fn_name);
|
||||
let fn_scope_struct = format_ident!("{}_Scoped", fn_name);
|
||||
let fn_name_async = format_ident!("{}_async", fn_name);
|
||||
let init_fn_register = format_ident!("{}_register_union", fn_name);
|
||||
let shutdown_fn = format_ident!("{}_shutdown", fn_name);
|
||||
|
||||
let param_unpacking = param_names.iter().enumerate().map(|(i, name)| {
|
||||
|
@ -109,13 +115,17 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let output = quote! {
|
||||
pub fn #fn_name(#(#param_names: #param_types),*) -> #return_type {
|
||||
let i: comrade::serde_json::Value = comrade::serde_json::to_value( (#(#param_names),*) ).unwrap();
|
||||
serde_json::from_value(comrade::UNION.get(stringify!(#fn_name)).unwrap().send(i)).unwrap()
|
||||
serde_json::from_value(comrade::UNION.get(stringify!(#fn_name)).expect("Function call is not registered in UNION").send(i)).unwrap()
|
||||
}
|
||||
|
||||
#[doc = "Will run the function non blocking returning a `JobResult<_>` for fetching a result later."]
|
||||
pub fn #fn_name_async(#(#param_names: #param_types),*) -> comrade::job::JobResult<comrade::serde_json::Value> {
|
||||
let i: comrade::serde_json::Value = comrade::serde_json::to_value( (#(#param_names),*) ).unwrap();
|
||||
comrade::UNION.get(stringify!(#fn_name)).unwrap().send_async(i)
|
||||
if let Some(dispatch) = comrade::UNION.get(stringify!(#fn_name)) {
|
||||
dispatch.send_async(i)
|
||||
} else {
|
||||
panic!("Function call {} is not registered in UNION", stringify!(#fn_name))
|
||||
}
|
||||
}
|
||||
|
||||
fn #wrapper_fn(task: JobOrder<comrade::serde_json::Value, comrade::serde_json::Value>) {
|
||||
|
@ -131,7 +141,7 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
task.done(comrade::serde_json::to_value(&res).unwrap());
|
||||
}
|
||||
|
||||
pub fn #worker_fn(recv: Receiver<JobOrder<comrade::serde_json::Value, comrade::serde_json::Value>>) {
|
||||
pub fn #worker_fn(recv: comrade::job::TaskReceiverBackend<comrade::serde_json::Value, comrade::serde_json::Value>) {
|
||||
let mut metrics = (0, 0);
|
||||
loop {
|
||||
let task = recv.recv();
|
||||
|
@ -167,17 +177,59 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let mut dispatchers = Vec::new();
|
||||
let mut s = sm;
|
||||
|
||||
log::info!("Initializing worker {} with {} threads", stringify!(#worker_fn), #worker_count);
|
||||
|
||||
for i in 0..#worker_count {
|
||||
let (dispatch, recv): (JobDispatcher<_, _>, Receiver<JobOrder<_, _>>) = JobDispatcher::new();
|
||||
|
||||
s = s.register(
|
||||
&format!("{}_{i}", stringify!(#worker_fn)),
|
||||
move |_| {
|
||||
#worker_fn(recv.clone())
|
||||
#worker_fn(comrade::job::TaskReceiverBackend::Local(recv.clone()))
|
||||
}
|
||||
);
|
||||
|
||||
dispatchers.push(dispatch);
|
||||
dispatchers.push(comrade::job::Dispatcher::Local(dispatch));
|
||||
}
|
||||
|
||||
comrade::UNION.insert(stringify!(#fn_name), comrade::job::JobMultiplexer::from(dispatchers));
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
|
||||
#[doc = "Register worker union on Valkey backend without starting local workers."]
|
||||
pub fn #init_fn_register() {
|
||||
let mut dispatchers = Vec::new();
|
||||
|
||||
log::info!("Registering worker union {}", stringify!(#worker_fn));
|
||||
|
||||
let dispatch = comrade::job::ValkeyJobDispatcher::<_, _>::new_topic(stringify!(#worker_fn), false);
|
||||
dispatchers.push(comrade::job::Dispatcher::Union(dispatch));
|
||||
|
||||
comrade::UNION.insert(stringify!(#fn_name), comrade::job::JobMultiplexer::from(dispatchers));
|
||||
}
|
||||
|
||||
#[doc = "Initialize worker threads on `ServiceManager` with Valkey backend"]
|
||||
pub fn #init_fn_union(sm: ServiceManager) -> ServiceManager {
|
||||
let mut dispatchers = Vec::new();
|
||||
let mut s = sm;
|
||||
|
||||
log::info!("Initializing worker union {} with {} threads", stringify!(#worker_fn), #worker_count);
|
||||
|
||||
for i in 0..#worker_count {
|
||||
let dispatch = comrade::job::ValkeyJobDispatcher::<_, _>::new_topic(stringify!(#worker_fn), true);
|
||||
|
||||
let recv = dispatch.clone();
|
||||
|
||||
s = s.register(
|
||||
&format!("{}_union_{i}", stringify!(#worker_fn)),
|
||||
move |_| {
|
||||
#worker_fn(comrade::job::TaskReceiverBackend::Union(recv.clone()))
|
||||
}
|
||||
);
|
||||
|
||||
dispatchers.push(comrade::job::Dispatcher::Union(dispatch));
|
||||
}
|
||||
|
||||
comrade::UNION.insert(stringify!(#fn_name), comrade::job::JobMultiplexer::from(dispatchers));
|
||||
|
@ -206,6 +258,12 @@ pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
let sm = #init_fn(sm);
|
||||
(sm, #fn_scope_struct {})
|
||||
}
|
||||
|
||||
#[doc = "Initialize a worker union on `ServiceManager` on a scoped lifetime"]
|
||||
pub fn #init_fn_scoped_union(sm: ServiceManager) -> (ServiceManager, #fn_scope_struct) {
|
||||
let sm = #init_fn_union(sm);
|
||||
(sm, #fn_scope_struct {})
|
||||
}
|
||||
};
|
||||
|
||||
output.into()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue