A very primitive Actor implementation#468
Conversation
adamruzicka
left a comment
There was a problem hiding this comment.
I finally had some time to read this and the concurrent ruby docs again and I must admit I was a bit rusty on it. It seems an actor was the thing I had in mind. Considering agents are more about state, an actor would most likely be a better fit. Sorry about that.
Apart from the katello queue, I'd eventually like to migrate this mqtt re-sending part of sp-rex-ssh to this rather just spawning actors ad-hoc.
| @agents[name] | ||
| end | ||
|
|
||
| def register_agent(name, value:, observers: []) |
There was a problem hiding this comment.
Rather than being able to register agents on the fly, I was thinking about going more declarative route. World configuration would have an extra_agents option (not set on the name), which would accept a hash name-class pairs.
When used with foreman, foreman-tasks would provide an option through which plugins could register their agents and foreman-tasks would pass the hash with all the agents to dynflow when it actually initializes it.
| def post_initialization | ||
| @delayed_executor ||= try_spawn(:delayed_executor, Coordinator::DelayedExecutorLock) | ||
| @execution_plan_cleaner ||= try_spawn(:execution_plan_cleaner, Coordinator::ExecutionPlanCleanerLock) | ||
| # TODO: is an agent executor needed? |
| class AgentLock < LockByWorld | ||
| def initialize(world, agent_name) | ||
| super(world) | ||
| @data[:id] = self.class.lock_id(agent_name) | ||
| end | ||
|
|
||
| def self.lock_id(agent_name) | ||
| "agent:#{agent_name}" | ||
| end | ||
| end |
There was a problem hiding this comment.
This would mean two things:
- the agent would be globally unique
- the agent would only be spawned during world initialization
I don't see any mechanism that would cause other world to try and start the agent if the world that currently holds the lock went away. We could either have the worlds themselves retry or always spawn the agents in all the worlds, but let them compete for the lock.
There was a problem hiding this comment.
I was thinking more toward the latter but only through the lens of "how many places does the applicability host queue need to be cleared from?" Other use cases may not want global uniqueness at all.
There was a problem hiding this comment.
I don't see any mechanism that would cause other world to try and start the agent if the world that currently holds the lock went away
Were you asking this simply from the point of safety or is there a general case where a world may go away and not be replaced by another that would restart the actor?
There was a problem hiding this comment.
Mostly from the point of safety.
General cases could be found once in multi-executor deployments, but those are pretty rare and even then you'd have to try hard to trigger it.
| # Configuration parameters: CountComments, CountAsOne, ExcludedMethods. | ||
| Metrics/MethodLength: | ||
| Max: 47 | ||
| Max: 48 |
There was a problem hiding this comment.
Eh, sure, I don't feel strongly about this either way.
There was a problem hiding this comment.
I wasn't sure if rubocop would gate running of tests so I quickly did this. No intention of keeping it
|
Moving to draft as this is really just an experiment at the moment. |
I was able to pull something basic together pretty quickly. It works with my related Katello change https://github.com/jturel/katello/pull/1/changes Of course, it's lacking in the finer details.