-
Notifications
You must be signed in to change notification settings - Fork 231
Tell workers to kill operations the scheduler no longer has executing on them #2693
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
Changes from all commits
8a76e1a
52cb8aa
d7394cd
ed0a426
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,7 +20,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; | |
| use nativelink_error::{Code, Error, ResultExt}; | ||
| use nativelink_metric::MetricsComponent; | ||
| use nativelink_proto::com::github::trace_machina::nativelink::remote_execution::{ | ||
| ConnectionResult, StartExecute, UpdateForWorker, update_for_worker, | ||
| ConnectionResult, KillOperationRequest, StartExecute, UpdateForWorker, update_for_worker, | ||
| }; | ||
| use nativelink_util::action_messages::{ActionInfo, OperationId, WorkerId}; | ||
| use nativelink_util::metrics_utils::{AsyncCounterWrapper, CounterWithTime, FuncCounterWrapper}; | ||
|
|
@@ -56,12 +56,19 @@ pub enum WorkerUpdate { | |
|
|
||
| /// Request that the worker is no longer in the pool and may discard any jobs. | ||
| Disconnect, | ||
|
|
||
| /// Requests that the worker stop executing this operation. | ||
| KillOperation(OperationId), | ||
| } | ||
|
|
||
| #[derive(Debug, MetricsComponent)] | ||
| pub struct PendingActionInfoData { | ||
| #[metric] | ||
| pub action_info: ActionInfoWithProps, | ||
| /// Set once the worker has been told to kill this operation. Its later | ||
| /// report then only settles the worker's own bookkeeping. | ||
| #[metric(help = "If the worker has been asked to kill this operation.")] | ||
| pub kill_requested: bool, | ||
| } | ||
|
|
||
| /// Represents a connection to a worker and used as the medium to | ||
|
|
@@ -164,6 +171,7 @@ impl Worker { | |
| run_action: AsyncCounterWrapper::default(), | ||
| keep_alive: FuncCounterWrapper::default(), | ||
| notify_disconnect: CounterWithTime::default(), | ||
| kill_operation: CounterWithTime::default(), | ||
| }), | ||
| } | ||
| } | ||
|
|
@@ -191,9 +199,37 @@ impl Worker { | |
| self.metrics.notify_disconnect.inc(); | ||
| send_msg_to_worker(&self.tx, update_for_worker::Update::Disconnect(())) | ||
| } | ||
| WorkerUpdate::KillOperation(operation_id) => { | ||
| let pending_action_info = self | ||
| .running_action_infos | ||
| .get_mut(&operation_id) | ||
| .err_tip(|| { | ||
| format!( | ||
| "Worker {} asked to kill operation {operation_id} that is not running on it", | ||
| self.id | ||
| ) | ||
| })?; | ||
| // Set before the send so a racing update_action cannot slip | ||
| // through in between. | ||
| pending_action_info.kill_requested = true; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: |
||
| self.metrics.kill_operation.inc(); | ||
| send_msg_to_worker( | ||
| &self.tx, | ||
| update_for_worker::Update::KillOperationRequest(KillOperationRequest { | ||
| operation_id: operation_id.to_string(), | ||
| }), | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// Whether the worker has been told to kill this operation. | ||
| pub(crate) fn is_kill_requested(&self, operation_id: &OperationId) -> bool { | ||
| self.running_action_infos | ||
| .get(operation_id) | ||
| .is_some_and(|pending_action_info| pending_action_info.kill_requested) | ||
| } | ||
|
|
||
| pub fn keep_alive(&mut self) -> Result<(), Error> { | ||
| let tx = &mut self.tx; | ||
| let id = &self.id; | ||
|
|
@@ -228,7 +264,13 @@ impl Worker { | |
| worker_platform_properties, | ||
| &action_info.platform_properties, | ||
| ); | ||
| running_action_infos.insert(operation_id, PendingActionInfoData { action_info }); | ||
| running_action_infos.insert( | ||
| operation_id, | ||
| PendingActionInfoData { | ||
| action_info, | ||
| kill_requested: false, | ||
| }, | ||
| ); | ||
|
|
||
| send_msg_to_worker(tx, update_for_worker::Update::StartAction(start_execute)) | ||
| }) | ||
|
|
@@ -317,4 +359,6 @@ struct Metrics { | |
| keep_alive: FuncCounterWrapper, | ||
| #[metric(help = "The number of notify_disconnect sent to this worker.")] | ||
| notify_disconnect: CounterWithTime, | ||
| #[metric(help = "The number of kill_operation sent to this worker.")] | ||
| kill_operation: CounterWithTime, | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slot-leak corner for a live-but-unresponsive worker. Once
kill_requestedis set, the op is filtered out of every future sweep here, and nothing else re-sends or times out the kill itself. A dead worker is recovered byremove_timedout_workers, but a live worker that drops or ignores theKillOperationRequestholds its slot indefinitely whileupdate_actionsilently swallows its updates (L377). Worth a comment noting that keepalive-timeout eviction is the sole recovery path here, or a bounded re-send.