You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Looking to improve a few things and gather wider feedback based on suggestions from @moosingin3space
Task returns
The first idea is around getting a return type or error out of a worker thread. The idea being that if a worker task completes, or bubbles up an error, you can get to that result. My current inclination is to add another generic for the task return type:
diff --git a/src/worker.rs b/src/worker.rs
index 0c45c1c..0931007 100644
--- a/src/worker.rs+++ b/src/worker.rs@@ -7,7 +7,7 @@ use crate::request::TenoriteRequest;
/// This trait specifies the worker end of the service. the `task()` method is
/// what implements the server side logic.
#[async_trait]
-pub trait TenoriteWorker<Request, Response, Error, TaskConfig>+pub trait TenoriteWorker<Request, Response, Error, TaskConfig, TaskResult>
where Request: Debug,
Response: Debug,
Error: Debug,
@@ -16,5 +16,5 @@ pub trait TenoriteWorker<Request, Response, Error, TaskConfig>
async fn task(
mut receiver: Receiver<TenoriteRequest<Request, Response, Error>>,
config: TaskConfig,
- );+ ) -> TaskResult;
}
This feels like a pretty simple and permissive option. Currently returns aren't supported so the JoinHandle wraps the () type. This would instead use the generic JoinHandle<TaskResult>
Another alternative that came up was having an abstracted handler structure returned that has some additional channels for errors or some other kind of control plane specific use
Workers gone awry
Worker panic handling or better reactions if a service's 💩 hits the fan. This would be nice but I don't currently have any good solutions
More concurrent concurrency
There are probably a few other good async message patterns that can be similarly abstracted. The core tokio channel types are simple enough to use but probably other good models or components are waiting to be found. I don't have any concrete ideas but some thoughts are:
pipeline pattern
instead of returning a result to the caller, return to an additional pipeline block or use an async closure
tower or something else may already fit this need pretty well
a fan-out/fan-in pattern
requests into a single source channel distribute to a parralel task pool and sink into a single output channel
pubsub pattern
subscribe to channel, listening for an enum variant?
router / load balancer / proxy pattern
similar to current client/service model but with a dynamic routing element
proxies requests based on user-pluggable scheduler or commonly used patterns
Cleaner Implementation
I'm hopeful there's also a way to simplify all the generics clutter when implementing a service. I've been experimenting with macros and maybe there's a good pattern there for simplifying the process of getting all the right types where they need to go without being an eyesore with minimal cognitive load.
Alternatively, maybe another layer can be used, some type of container for a group of related generic types.
Assumptions check
A few trade-offs were made to achieve a nice usage pattern, and some core choices were hastily made to quiet that pesky compiler with all its helpful advice. Sure cargo, it's all 'static and Send or Debug or whatever you want from me! I like this usage pattern so I'll just give you all the trait bounds you want!!
This mostly happened in TenoriteService, but if anyone finds these needlessly restricting or has other assumptions to challenge I'm very open to suggestions on that front
The text was updated successfully, but these errors were encountered:
Looking to improve a few things and gather wider feedback based on suggestions from @moosingin3space
Task returns
The first idea is around getting a return type or error out of a worker thread. The idea being that if a worker task completes, or bubbles up an error, you can get to that result. My current inclination is to add another generic for the task return type:
This feels like a pretty simple and permissive option. Currently returns aren't supported so the
JoinHandle
wraps the()
type. This would instead use the genericJoinHandle<TaskResult>
Another alternative that came up was having an abstracted handler structure returned that has some additional channels for errors or some other kind of control plane specific use
Workers gone awry
Worker panic handling or better reactions if a service's 💩 hits the fan. This would be nice but I don't currently have any good solutions
More concurrent concurrency
There are probably a few other good async message patterns that can be similarly abstracted. The core tokio channel types are simple enough to use but probably other good models or components are waiting to be found. I don't have any concrete ideas but some thoughts are:
Cleaner Implementation
I'm hopeful there's also a way to simplify all the generics clutter when implementing a service. I've been experimenting with macros and maybe there's a good pattern there for simplifying the process of getting all the right types where they need to go
without being an eyesorewith minimal cognitive load.Alternatively, maybe another layer can be used, some type of container for a group of related generic types.
Assumptions check
A few trade-offs were made to achieve a nice usage pattern, and some core choices were hastily made to quiet that pesky compiler with all its helpful advice. Sure cargo, it's all
'static
andSend
orDebug
or whatever you want from me! I like this usage pattern so I'll just give you all the trait bounds you want!!This mostly happened in TenoriteService, but if anyone finds these needlessly restricting or has other assumptions to challenge I'm very open to suggestions on that front
The text was updated successfully, but these errors were encountered: