-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Assign multiple Actors to a Builder #3
Comments
So my first instinct is to do something like this: https://gist.github.com/idanarye/25b24d72e30edf23cf3057c4b62b506c. Basically I'm putting a part of the GUI into a a container, and use In that gist I'm using Of course - this is assuming you are splitting the actors based on the GUI, where each actor is responsible for one subtree of the GUI and receives all the signals from that subtree (as long as they don't come from a subtree of that subtree that was taken by another actor). If this is not the case, then we may need a more elaborate scheme - maybe namespacing the signals? |
At the moment, I am referring to widgets from within multiple actors. For example, the header bar is shown and hidden by the fullscreen actor, but other actors hold a reference to it as well in order to add buttons etc. I also have a
How does this work internally? Is there anything preventing me to have multiple actors listen on a signal if they use the same name? If I can have multiple actors share a widget, why shouldn't they share signals as well? |
I thought calling |
Thanks for the insights.
I expected this as well, but it doesn't. Apparently it isn't intended to be called multiple times. Fixing this would require the implementation to switch to using I don't know about the behavior of calling |
So the semantic of those methods is: you can call them multiple times, only the first callback for each signal is registered. |
I'm not a big fan of using unsafe FFI outside the crate that's supposed to wrap it. I'd like to propose a different solution - using an actor to route the signals: https://gist.github.com/idanarye/de191a9b42fd5b5afbc0dd3ceef83b6e I can start with a simple router that just clones the signal and transmits it to all registered recipients, and in future updates, if the need arises, I can add routers that route by namespace, or by tags, or by parsing the arguments, and it can all be composed to fit the projects' requirements. |
Oh, I didn't notice this. There are no bindings for this function. I've also had a closer look at it, and the way Regarding your proposal, do I understand it correctly that all actors that potentially share signals also share a Message enum? So they all get all messages, even though they probably ignore most of them? I have a vague idea in mind on how this could be done in a way that keeps them separate, but I'll have to think about that one some more. |
With the basic router - yet. But I can probably work a more advanced router. I envision something like that: #[derive(Clone, woab::SignalNamespace)]
pub enum Namespace {
#[namespace(root)]
Root(RootSignal),
Namespace1(Namespace1Signal),
Namespace2(Namespace2Signal),
}
#[derive(Clone, woab::BuilderSignal)]
pub enum RootSignal {
Signal1,
Signal2,
}
#[derive(Clone, woab::BuilderSignal)]
pub enum Namespace1Signal {
Signal3,
Signal4,
}
#[derive(Clone, woab::BuilderSignal)]
pub enum Namespace2Signal {
Signal5,
Signal6,
} This represents the signals:
And each actor can use its own namespace: impl actix::StreamHandler<RootSignal> for Actor1 { ... }
impl actix::StreamHandler<Namespace1Signal> for Actor2 { ... }
impl actix::StreamHandler<Namespace2Signal> for Actor3 { ... } Of course, nothing stops two actors from using the same namespace - they'll each get a copy of the signal - and nothing stops one actor from using two namespaces - it just has to be a Routing registration can use the same message as the basic router, but we'd have to specify the specific signal type because the router supports multiple signals (though if the actor only has one signal I think Rust can infer that): Actor1::create(|ctx| {
let stream = woab::register_route<RootSignal>(router_ctx.address().recipient()).unwrap();
Actor1::add_stream(stream, ctx);
Actor1 { ... }
});
Actor2::create(|ctx| {
let stream = woab::register_route<Namespace1Signal>(router_ctx.address().recipient()).unwrap();
Actor2::add_stream(stream, ctx);
Actor2 { ... }
});
Actor3::create(|ctx| {
let stream = woab::register_route<Namespace2Signal>(router_ctx.address().recipient()).unwrap();
Actor3::add_stream(stream, ctx);
Actor3 { ... }
}); |
I feel like I now know enough about the problem and the code base that I'd like to try to solve this myself (though it may take some time). |
When you say "solve" you mean "do a PR" or are you going to solve this externally, in your own code (e.g. with manual routing)? If you are going to solve this externally I may still want to add routing facilities to WoAB somewhere in the future. Either way, I should probably finish #2 and make a release without waiting for this ticket, because while the multiple builders problem is not relevant for all architecture (it's not relevant for mine. It is relevant for yours. So far this is our entire sample...) and can be worked around externally, the signal return value prevents the usage of certain signals, which is a serious issue. |
I'm hoping to make a PR in the end, yes :) |
My UI is pretty static, as in it defines all in one file and there are not many changes to the hierarchy during the runtime of the program. Therefore, I don't really need factories, only one Builder instance is enough.
But I'd still like to split my design into multiple actors: for example, the full screen handling is a separate strand of logic that works independently of the rest and thus can be encapsulated as a separate actor.
I can create multiple
BuilderUtilizer
instances from one builder object and for the widgets it works fine. But for the signals it does not, only the first actor will get all the signals and all others won't.The text was updated successfully, but these errors were encountered: