-
-
Notifications
You must be signed in to change notification settings - Fork 39
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
Registered subjects #45
Comments
Hello! Thanks for bringing this up, I've been thinking about this a bunch too over the last few years :) This design enables a subject to effectively be inherited by a new process, removing the need to propagate a subject when a process is restarted/replaced. It does not remove that need to get the subject the first time round, like Erlang is able to with its names. I think that's likely OK! With this addition it would be possible for a subject to not have a pid. We would need to make the function for getting that return an option? It would also mean that actor.start could technically succeed but not return a pid. Do we want to rethink the API there? For example, we might want to make it return a pid and also some other data rather than always a subject. This would also enable us to return other data from the start function, that would be cool. For global names I'm not sure how we would be able to construct them in a type safe way. Perhaps this should be left for later as it's much more complex. |
Yes!
Agreed :)
Yes, or what /// Look up a process by name, returning the pid if it exists.
///
@external(erlang, "gleam_erlang_ffi", "process_named")
pub fn named(name: Atom) -> Result(Pid, Nil) The function However, this would then be a breaking change, not sure how you feel about that?
Why? I was thinking of keeping the API the same and return a
Isn't it the same but then just calling |
Another thing we may want think about is how we deal with sending to a named subject where the process is dead. Should that result in an error? For
We're definitely going to need to make some breaking changes here, so I think it's good to think about what else we would want to break here. Some candidates on my mind at the moment are:
Is there anything else?
Yes. In a distributed scenario there is no guarantee that the same code is running on both nodes. Worse: it commonly will not be the same. |
Erlang does throw an error in this case as the docs of The function fails with a badarg run-time error if Dest is an atom name, but this name is not registered. This is the only case when send fails for an unreachable destination Dest (of correct type). For monitoring erlang does not throw an error but instead sends a
We already kind of have an error for this right? The type
Clear. I will play around with a few ideas and submit a draft PR for the changes in
Sounds good! But these changes you're talking have to be made in
Not that I can think of now.
Clear. |
@lpil I have a first try on the named-subjects branch, apart from introducing // Create a new `Subject` owned by the current process and registered with
/// the given name. This function may fail for the same reasons as `register/2`.
///
pub fn new_named_subject(name: Atom) -> Result(Subject(message), Nil) {
let register_result = register(self(), name)
result.map(register_result, fn(_) {
Subject(destination: NamedDestination(name), tag: erlang.make_reference())
})
} it introduces a
pub type SubjectOwner {
PidDestination(Pid)
NamedDestination(Atom)
}
Do you think this is a direction that makes sense? |
We can't think about changes in the context of just one package, we need to think about the entire ecosystem before making any changes here as it's such an important part of Gleam.
The point of the function is to return the pid so it must continue to return a pid. Otherwise everyone has to write the same boilerplate case expression around this function, which isn't very useful.
I'm not sure. It is strange to me that it returns ok if it is a pid and the process is dead, but an error if it is a name and it is dead. |
Makes sense 👍
You mean
Yes, I was also thinking of this. This is currently what erlang does (sending to dead pid -> no error, sending to unregistered name -> error), that's why I was following it. But I can see the benefits of unifying this. So then we would check for the 'liveness' for both the registered and unregistered processes? |
Hello! Sorry I'm taking so long here, I'm rather swamped. I've not had time to read your branch but I hope to soon. I don't think we should copy from Erlang for the error cases, rather we want to have an API that is designed for Gleam's goals and constraints. |
The README of gleam/otp mentions
There is no support for named processes. They are untyped global mutable variables which may be uninitialized, more research is needed to find a suitable type safe alternative.
I just wanted to drop a thought here and see if we can further explore a solution to this.
We now have the
Subject
, which is an opaque type:As far as I understood is that the current approach to using supervised actors is to send the subject to the parent proces. I propose that we keep it like that, but instead of
new_subject
in the actor we do something likenew_local_subject(name)
and haveSo basically everything remains the same but we don't need to handle actor restarts in our code explicitly: when the actor restarts it will register again under the same name.
Local, global and possible in the future custom registration can be done like in erlang:
https://github.com/erlang/otp/blob/79bc8234396a4f619f40dadfb8458064ab29aa85/lib/stdlib/src/gen.erl#L622-L640
Are there any problems with this solution?
The text was updated successfully, but these errors were encountered: