derekkraan / horde

Horde is a distributed Supervisor and Registry backed by DeltaCrdt
MIT License
1.32k stars 106 forks source link

Horde Process topology #230

Closed sleipnir closed 1 year ago

sleipnir commented 3 years ago

Hello recently I had the need to start a process on a specific Node and still make this process managed by Horde.DynamicSupervisor and Horde.Registry, unfortunately it is not currently possible to register a process on a specific Node via Horde. It might be possible to accomplish this by creating a customized Horde.DistributionStrategy strategy, but the signature of choose_node did not seem flexible to me so that I could provide the correct topology information expected to start the process at a specific Node. Would it be possible to accomplish this in any way?

Thanks!

arjan commented 3 years ago

choose_node receives all members of the cluster plus the identifier, so that means that you could just pick one of the members based on the identifer?

sleipnir commented 3 years ago

@arjan Yes I agree. As long as I know at that point which identifier to choose. We would have to receive some information about which preferred Node the user wants to connect this Process

sleipnir commented 3 years ago

This could be passed as an option to the DynamicSupervisor of the process.

redrabbit commented 3 years ago

@sleipnir, I'm in the same boat. Currently looking for a way to start my processes on a specific node. My app require a specific node based on volume id (disk storage). Did you find a way to accomplish your goal?

@arjan, it seems that the identifier given to choose_node/2 is the hash of the child_spec (without the :id) in Horde.DynamicSupervisor.start_child/2. In my case it's not feasible because the params given to :start would differ between processes.

https://github.com/derekkraan/horde/blob/c00f77d080152cc160af390069169733f1afd0d8/lib/horde/dynamic_supervisor_impl.ex#L754

I think the changes made in #128 and being a fix for compatibility issues with Elixir.DynamicSupervisor broke the way of defining custom distribution strategies based on a specific identifier (or at least making it very cumbersome).

sleipnir commented 3 years ago

@sleipnir, I'm in the same boat. Currently looking for a way to start my processes on a specific node. My app require a specific node based on volume id (disk storage). Did you find a way to accomplish your goal?

@arjan, it seems that the identifier given to choose_node/2 is the hash of the child_spec (without the :id) in Horde.DynamicSupervisor.start_child/2. In my case it's not feasible because the params given to :start would differ between processes.

https://github.com/derekkraan/horde/blob/c00f77d080152cc160af390069169733f1afd0d8/lib/horde/dynamic_supervisor_impl.ex#L754

@redrabbit Unfortunately I couldn't find a solution and ended up using a singleton process on the cluster. Still trying to find time to send a PR with a proposal for this feature but it's a little difficult

arjan commented 3 years ago

@redrabbit the second argument of choose_node/2 is the list of members. If you filter that list first you can control the set of nodes which get selected. This is how I implemented it:

        def choose_node(identifier, members) do
          members = Enum.filter(members, fn member -> ... end)

          Horde.UniformDistribution.choose_node(identifier, members)
        end
redrabbit commented 3 years ago

@arjan like I stated in my previous comment, the identifier passed to choose_node/2 is not very usable because it's the hash of child_spec without :id. So how do I filter my members based on the identifier?

arjan commented 3 years ago

I'm sorry, I did not read it carefully enough. I think it would be a nice addition to add the original child_spec as a third argument to the choose_node callback function.

CimimUxMaio commented 3 years ago

¿Any updates on this issue? I'm having the same problem, I need some of the child's info to filter out members from the list. ¿Any new ideas on how to work around this?

arjan commented 3 years ago

It seems easy enough to create a branch add this third argument, and then create a PR for it?

AFAICT you only need to change these lines

fmbraga commented 2 years ago

choose_node/2 receives a child_spec. Since child_spec is an ordinary map, you could add a :preferred_node into it, and choose_node would have something to decide where to start your process.

sleipnir commented 1 year ago

Closing this because PR https://github.com/derekkraan/horde/pull/239 can solve the problem.