Coverage Report

Created: 2026-11-13 23:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/build/source/nativelink-scheduler/src/worker_scheduler.rs
Line
Count
Source
1
// Copyright 2024 Trace Machina, Inc. All rights reserved.
2
//
3
// Licensed under the Functional Source License, Version 1.1, Apache 2.0 Future License (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    See LICENSE file for details
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use std::collections::HashMap;
16
17
use async_trait::async_trait;
18
use nativelink_error::Error;
19
use nativelink_metric::RootMetricsComponent;
20
use nativelink_proto::com::github::trace_machina::nativelink::remote_execution::{
21
    ActionResourceUsage, WorkerLoad,
22
};
23
use nativelink_util::action_messages::{OperationId, WorkerId};
24
use nativelink_util::operation_state_manager::UpdateOperationType;
25
use nativelink_util::shutdown_guard::ShutdownGuard;
26
27
use crate::platform_property_manager::PlatformPropertyManager;
28
use crate::worker::{Worker, WorkerTimestamp};
29
30
/// `WorkerScheduler` interface is responsible for interactions between the scheduler
31
/// and worker related operations.
32
/// One connected worker, as the admin API reports it. Property values are
33
/// strings on both maps, the way they were registered.
34
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
35
pub struct WorkerSummary {
36
    pub id: String,
37
    pub running_actions: u32,
38
    pub max_inflight_tasks: u64,
39
    pub is_paused: bool,
40
    pub is_draining: bool,
41
    /// Seconds since the epoch of the worker's last message.
42
    pub last_update_timestamp: u64,
43
    /// What the worker registered with.
44
    pub platform_properties: HashMap<String, String>,
45
    /// What is left after the running actions' reservations.
46
    pub available_platform_properties: HashMap<String, String>,
47
    /// What the worker last reported having to spare, if it reports.
48
    pub free_memory_kb: Option<u64>,
49
}
50
51
#[async_trait]
52
pub trait WorkerScheduler: Sync + Send + Unpin + RootMetricsComponent + 'static {
53
    /// Returns the platform property manager.
54
    fn get_platform_property_manager(&self) -> &PlatformPropertyManager;
55
56
    /// Adds a worker to the scheduler and begin using it to execute actions (when able).
57
    async fn add_worker(&self, worker: Worker) -> Result<(), Error>;
58
59
    /// The worker took the dispatched operation.
60
    async fn worker_dispatch_accepted(
61
        &self,
62
        worker_id: &WorkerId,
63
        operation_id: &OperationId,
64
    ) -> Result<(), Error>;
65
66
    /// The worker will not run the dispatched operation; `reason` is the
67
    /// worker's word for why, `needs_kb` what it said the action wanted
68
    /// when the reason was load.
69
    async fn worker_dispatch_declined(
70
        &self,
71
        worker_id: &WorkerId,
72
        operation_id: &OperationId,
73
        reason: String,
74
        needs_kb: Option<u64>,
75
    ) -> Result<(), Error>;
76
77
    /// Updates the status of an action to the scheduler from the worker.
78
    async fn update_action(
79
        &self,
80
        worker_id: &WorkerId,
81
        operation_id: &OperationId,
82
        update: UpdateOperationType,
83
    ) -> Result<(), Error>;
84
85
    /// Records worker-observed resource usage for a running action.
86
    async fn record_action_resource_usage(
87
        &self,
88
        _worker_id: &WorkerId,
89
        _operation_id: &OperationId,
90
        _resource_usage: ActionResourceUsage,
91
0
    ) -> Result<(), Error> {
92
        Ok(())
93
0
    }
94
95
    /// Event for when the keep alive message was received from the worker,
96
    /// with what the worker reported having to spare, if it did.
97
    async fn worker_keep_alive_received(
98
        &self,
99
        worker_id: &WorkerId,
100
        timestamp: WorkerTimestamp,
101
        load: Option<WorkerLoad>,
102
    ) -> Result<(), Error>;
103
104
    /// A keepalive said which operations the worker is running. An
105
    /// acknowledged operation the worker leaves out of two reports in a row
106
    /// finished without its result reaching the scheduler; it is released
107
    /// and requeued. Ignored unless the scheduler tracks what it dispatched.
108
    async fn worker_running_operations_reported(
109
        &self,
110
        _worker_id: &WorkerId,
111
        _operation_ids: Vec<OperationId>,
112
0
    ) -> Result<(), Error> {
113
        Ok(())
114
0
    }
115
116
    /// A keepalive said how much memory the worker has sampled so far for
117
    /// each running operation, as `(operation, peak KiB)`. Kept against the
118
    /// dispatch so a lost worker's actions can be judged by it (RFC-0018).
119
    async fn worker_operation_memory_reported(
120
        &self,
121
        _worker_id: &WorkerId,
122
        _peaks: Vec<(OperationId, u64)>,
123
0
    ) -> Result<(), Error> {
124
        Ok(())
125
0
    }
126
127
    /// Any other message from the worker (an acknowledgement, a decline, an
128
    /// execute result) proves it is alive. Unlike a keepalive it lifts no
129
    /// pause: a decline is not the worker saying it is ready to be asked
130
    /// again.
131
    async fn worker_liveness_refreshed(
132
        &self,
133
        worker_id: &WorkerId,
134
        timestamp: WorkerTimestamp,
135
    ) -> Result<(), Error>;
136
137
    /// Removes worker from pool and reschedule any tasks that might be running on it.
138
    async fn remove_worker(&self, worker_id: &WorkerId) -> Result<(), Error>;
139
140
    /// The worker's stream ended without a `GoingAway`: it crashed, was
141
    /// OOM-killed or lost its connection. Its actions requeue as a
142
    /// disconnect, so the retry cap names the worker rather than the job.
143
    async fn worker_disconnected(&self, worker_id: &WorkerId) -> Result<(), Error>;
144
145
    /// Evict all workers from the scheduler, setting their actions back to queued.
146
    async fn shutdown(&self, shutdown_guard: ShutdownGuard);
147
148
    /// Removes timed out workers from the pool. This is called periodically by an
149
    /// external source.
150
    async fn remove_timedout_workers(&self, now_timestamp: WorkerTimestamp) -> Result<(), Error>;
151
152
    /// Sets if the worker is draining or not.
153
    async fn set_drain_worker(&self, worker_id: &WorkerId, is_draining: bool) -> Result<(), Error>;
154
155
    /// Every connected worker as the scheduler sees it right now, for the
156
    /// admin API: what it advertised, what it has left, what it runs.
157
    async fn worker_snapshot(&self) -> Vec<WorkerSummary>;
158
159
    /// Tells workers to kill operations they are still running but the
160
    /// scheduler has finished, requeued or dropped without them (client
161
    /// timeouts and cancellations, execution deadlines, retries elsewhere).
162
    async fn kill_revoked_operations(&self) -> Result<(), Error>;
163
}