Improve scheduler actor#63
Conversation
this was done for two reasons: 1) the vm and agent actor caches have slightly different requirements, specifically around keys (actorid vs vmid) 2) the scheduler needs direct control of the cache so the cache can be updated in response to messages it forwards. being possibly up to 1 second out of date in this data could cause problems. In theory the scheduler could update the generic cache, but I don't think using a generic cache if we need to modify it directly anyway really makes sense. Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
Signed-off-by: Caleb Jones <caleb@calebgj.io>
scheduler affinity Signed-off-by: Caleb Jones <caleb@calebgj.io>
…k/odorobo into caleb/fix-scheduler-actor-cache
Signed-off-by: Caleb Jones <caleb@calebgj.io>
There was a problem hiding this comment.
clippy found more than 20 potential problems in the proposed changes. Check the Files changed tab for more details.
this also fixes an issue where if a VM is never linked (ex: it didnt boot) it would never be removed from the caches.
|
i will look at this when i get back home. have you run it through clippy? |
| ) -> Result<RemoteActorRef<AgentActor>, Report> { | ||
| let mut best_agent = None; | ||
| let mut best_agent_score = 0u32; | ||
| // someone should likely give caleb a firm talking to about code duplication due to this section, but things are just different enough that trying to make them one function requires usage of a lot of generics which feels even worse. so i dont know what to do. cappy please fix. i hate this. |
There was a problem hiding this comment.
i don't think that it's that big of a deal here tbh. it's functional and readable in a way that you might lose if you were to try to use generics.
| // todo: i dont like the way this cache is setup. I think we may need to change it later, but it is hard to figure out what the optimal solution is without doing it at least once. | ||
| // especially when we haven't fully made decisions about some other things. | ||
| // | ||
| // todo: we should improve the cache to not have agents and vms send the full data on every update. |
There was a problem hiding this comment.
i'm sure there are off the shelf delta libraries. hell, git's is pretty decent. i can look into this a bit probably? not necessary for this pr but worth putting in outline or something. or opening a new pr/issue.
| // I looked at kameo streams to make this better, but they aren't really intended for this kind of long term update use case. | ||
| // They use rust futures::stream which seems to be more intended for you have an iterator for example that will create data, but not like full on sending messages. | ||
| // This could likely be done pretty easily by having two get data messages. | ||
| // Option 1: One that creates a session and sends the full data and then only sends diffs after that. |
There was a problem hiding this comment.
this sounds more robust to me tbh
| // idk. will figure it out later. | ||
| // | ||
| // new related problem: i just realized vmid, actorid pairs dont have to be unique. | ||
| // if a vm is migrating from one actor to another, there might be two actors with the same vmid. |
There was a problem hiding this comment.
why was my first thought here to use a linked list
| // if a vm is migrating from one actor to another, there might be two actors with the same vmid. | ||
| // | ||
| // additional context (05/05/2026): we almost may need a way to store them without a ulid, due to how CH migration works. | ||
| // the question becomes if we want to abstract CH migration away entirely from the scheduler. |
There was a problem hiding this comment.
what would the scope be like on this? i don't think it needs to be through the scheduler, but i think the scheduler needs to integrate with it. we need to rebalance nodes occasionally.
| // the best solution for at least some of this is almost certainly having an external reliable DB (such as etcd) to store some of these things permanently. | ||
| // we will need that specifically for what VMs are supposed to be running, because if a large percentage of the cluster goes down, including the manager, we need a way to recover. | ||
| // and i dont think leaving that on dashboard which could have high latency is a good idea. | ||
| // alternatively we could have the other manager nodes try to keep track of that data, but i think we are going to run into issues with keeping the state consistent between all nodes. |
There was a problem hiding this comment.
yeah honestly i think it's worth having a separate distributed db for this tbh. we don't want it to be integrated with odorobo in any way beyond like... a docker compose stack kinda thing. if odorobo fails, the database must retain data as it was when odorobo went down. i wonder if we could host a db with anyone who we peer with like cloudflare?
|
|
||
| parent_actor_ref.link_remote(&vm_actor).await?; | ||
|
|
||
| let vm_actor_id = vm_actor.id(); |
There was a problem hiding this comment.
is there a reason you can't just pass vm_actor.id() for this since it only gets used in the keepalive_tasks.insert() function call?
There was a problem hiding this comment.
meant to leave this on line 151
| if let Ok(data) = actor_ref.ask(&GetVMInfo { vmid: None }).await { | ||
| let vmid = data.vmid; | ||
|
|
||
| vm_actorid_ulid_map.insert(actor_ref.id(), vmid); // should we be doing this on every loop? idk. but we at least need to do it on the first iteration given we don't know the mapping before that |
There was a problem hiding this comment.
i feel like that's a good way to eat a couple cycles if it's not necessary for each loop
| async fn on_update( | ||
| // this function intentionally only checks against the cache. this has some positives and negatives: | ||
| // positive: it will never trigger any network requests so its very fast, and having to do network requests for scoring whenever we want to schedule a vm is likely a bad idea | ||
| // negative: it technically has a delayed view of the cluster, meaning that some things that happened in the future, may not exist yet. so we need to be careful about how this is done so affinity rules are not accidentally broken. mostly this means, if we do anything that could affect the outcome of an affinity rule (ex: network request to an agent), we need to update the cache, before we do the action. |
There was a problem hiding this comment.
assuming anything later in the cache is referencing anything that changed as a result of this, i think it's fine. so like if you have multiple VM creations get scheduled, as long as each subsequent one references the one before it.
intended changes for this PR
All that is left is testing and review by another maintainer.