Repository navigation
feat(orchestrator): Refresh a container execution as soon as its pod or job changes - #428
morgan-wowk wants to merge 1 commit into
Conversation
…or job changes The running queue visits container executions round-robin by last_processed_at, so a pod that finished waits for every other active container execution to be visited first. ContainerTaskLauncher gets pop_changed_container_execution_ids(), which returns the container executions whose containers changed since the last call; it returns nothing unless a launcher overrides it. The Kubernetes launchers now record the container execution id annotation on the pods they launch (and so on job pod templates), and their pod and job informers record each changed object's container execution. Before selecting a running container execution, the orchestrator moves the changed ones that are still PENDING or RUNNING to the front of the queue with one UPDATE. Pods and jobs launched before this change carry no id and keep the round-robin.
| ) -> _TLaunchedContainer: | ||
| raise NotImplementedError() | ||
|
|
||
| def pop_changed_container_execution_ids(self) -> list[str]: |
There was a problem hiding this comment.
Interface change
Only the launcher knows which containers changed (its pod and job informers already see every change), while only the orchestrator decides which container executions to refresh next, so a single method on the launcher interface is the smallest way to pass that signal from one to the other. It defaults to [], so launchers that can't tell (Davies, local and Docker launchers, routers that don't delegate) keep the current round-robin with no changes, and it doesn't commit the interface to anything Kubernetes-specific.
There was a problem hiding this comment.
Alternatives that leave ContainerTaskLauncher unchanged:
- Orchestrator kwarg: OrchestratorService_Sql takes an optional function that returns the changed ids, and the deployment passes in the Kubernetes launcher's method.
- Push callback: Kubernetes launchers take an on_container_execution_changed callback that feeds a set the orchestrator owns.
- Optional capability: a separate Protocol, or a getattr check, that only Kubernetes launchers implement.
- Launcher writes to the DB: the informer moves the row to the front itself, but that breaks layering because launchers have no DB session.
- Downstream patch: keep it as a deployment-side monkeypatch, which is fragile because it depends on informer internals.
Why an interface addition?
It's the only option where the launcher reports changes and the orchestrator consumes them through the same typed contract as the rest of the launcher API. The default [] means no other launcher or deployment needs any change, while the alternatives either spread the wiring across each deployment or hide the same method behind a looser contract.
Problem
The running queue visits container executions round-robin by
last_processed_at. A pod that started or finished waits for every other active container execution to be visited first. The Kubernetes launchers already run pod and job informers, so the orchestrator could know right away which container executions changed.Changes
ContainerTaskLauncher.pop_changed_container_execution_ids()returns the container executions whose containers changed since the last call. The default returns[].common_annotations.CONTAINER_EXECUTION_ID_ANNOTATION_KEY, and so do job pod templates. The launcher's ownpod_annotationsdict is not mutated.MultiNamespaceInformertakes an optionalon_changecallback. It is registered for ADDED, MODIFIED and DELETED after the informer's initial list, so startup does not mark every existing object.pop_changed_container_execution_ids()call on, so a launcher nobody asks keeps no ids._KubernetesPodOrJobLauncherreturns the pod launcher's ids plus the job launcher's.internal_process_running_executions_queue()first moves the changed container executions that are still PENDING or RUNNING to the front of the queue. That is oneUPDATE ... SET last_processed_at = 1970-01-01.System impact
Production test
All three orchestrator PRs ran together in production (https://github.com/Shopify/oasis-backend/pull/843). That test patched the informer in; this PR builds the same behavior into the launchers. Before/after:
Related PRs
pop_changed_container_execution_ids(). Otherwise they get the default[].Testing
pytest tests: 593 passed.tests/test_orchestrator_changed_container_executions.pycovers:[]tests/launchers/kubernetes/test_kubernetes_launchers_changed_container_executions.pycovers:on_change