Create an API to retrieve the `HandlerId` of a `Worker` from its `WorkerBridge`
Summary
A user should be able to retrieve the HandlerId of a worker from its unique Bridge.
Motivation
Some Application potentially spawns many workers and needs to store a lot of Bridge within a HashMap; we could keep track of which Bridge is linked to which worker if that was implemented.
Detailed Explanation
We could develop an API to get the ID from the bridge.
let starting_worker = self.worker_spawner.callback({
let link = ctx.link().clone();
move |e| link.send_message(Msg::WorkerMsg(e))
}).spawn("/calculator.js");
starting_worker.send(());
self.workers.insert(starting_worker.handler_id(), starting_worker);
Drawbacks, Rationale, and Alternatives
I propose this design cause I believe it has not been thought of. I might be wrong; there might be another solution to retrieve the id, which I have not found.
The function would return usize.
I'm open to discussion if there are any drawbacks I am unaware of. For now, I don't think returning a usize could be an issue.
Unresolved Questions
N/A
Pinging @futursolo for their feedback
You should be able to do this with AnyMap.
let mut workers = anymap::AnyMap::new();
let worker = CalculatorWorker::spawner().spawn("/calculator.js");
workers.insert(worker);
workers.get::<WorkerBridge<CalculatorWorker>>().expect("failed to get worker");
There should be a convenient way to retrieve it.
I have seen in the markdown example that the handler_id is sent back in the output message.
#[derive(Debug)]
pub enum Msg<T> {
Respond { output: T, id: HandlerId },
}
Why do this if there is no way to make it match with a worker bridge?
If you find this modification pertinent, I would be happy to develop it as my first contribution to the project!
I have seen in the markdown example that the handler_id is sent back in the output message.
This is internal message for the worker itself. The output type is String.
The message is actually not needed in the example. It's there to demonstrate the usage of message.
https://github.com/rustwasm/gloo/blob/master/examples/markdown/src/lib.rs#L19
I propose this design cause I believe it has not been thought of. I might be wrong; there might be another solution to retrieve the id, which I have not found.
The function would return usize. I'm open to discussion if there are any drawbacks I am unaware of. For now, I don't think returning a usize could be an issue.
Reasons not to expose HandlerId on bridges:
- It is not guaranteed to be globally unique.
We currently provide no guarantee to
HandlerIds other than it can be used to distinguish bridges by a worker. - We may not assign a single
usizeas HandlerId if we were to expand workers to shared workers and service workers. (It could be a (MessageChannelId, BridgeId) tuple.)
I don't think it's a widely used practice to use ID-based APIs in Rust.
In rare occasion, when an ID is exposed, it is exposed as an opaque type and does not give access to the underlying usize.
https://doc.rust-lang.org/std/any/struct.TypeId.html
Personally, I would not like to see HandlerIds being exposed on the bridge side.
However, if there is a legitimate use case where an identifier cannot be given to bridges based on AnyMap or enum variants, it should be exposed as an opaque type like std::any::TypeId or tokio::task::Id and not usize.
I will leave the final decision to @hamza1311 .
I agree with not exposing the Id directly. If there's a need to expose the id, it can/should be done through an opaque type. If we were to change how the id is stored, it shouldn't be a breaking change.
I haven't had to use this crate myself so I can't comment on the need of it. I'd be happy to merge any PRs related to this. @futursolo, you can make the decision on if this should be added or not.
Just for the sake of the example:
When managing a bunch of workers, all are spawned to realize a specific task.
When the worker finishes his work, he must respond.
That would be very convenient if I could respond HandlerId as an Output, so I would know which bridge I can drop.
I would rather trust you with design patterns, being very new in the rust community.
@futursolo, feel free to close the issue
When the worker finishes his work, he must respond. That would be very convenient if I could respond HandlerId as an Output, so I would know which bridge I can drop.
I have created a proposal #251 to introduce functional workers that can run asynchronous tasks without them being identified by HandlerIds or WorkerBridges.