Add job tags (#15555)

# Description

This PR implements job tagging through the usage of a new `job tag`
command and a `--tag` for `job spawn`

Closes #15354

# User-Facing Changes

- New `job tag` command
- Job list may now have an additional `tag` column for the tag of jobs
(rows representing jobs without tags do not have this column filled)
- New `--tag` flag for `job spawn`

# Tests + Formatting

Integration tests are provided to test the newly implemented features

# After Submitting

Possibly document job tagging in the jobs documentation
This commit is contained in:
Renan Ribeiro
2025-04-21 09:08:00 -03:00
committed by GitHub
parent b5b63d2bf9
commit a1497716f1
11 changed files with 200 additions and 14 deletions

View File

@ -38,6 +38,10 @@ impl Jobs {
self.jobs.get(&id)
}
pub fn lookup_mut(&mut self, id: JobId) -> Option<&mut Job> {
self.jobs.get_mut(&id)
}
pub fn remove_job(&mut self, id: JobId) -> Option<Job> {
if self.last_frozen_job_id.is_some_and(|last| id == last) {
self.last_frozen_job_id = None;
@ -134,13 +138,15 @@ pub enum Job {
pub struct ThreadJob {
signals: Signals,
pids: Arc<Mutex<HashSet<u32>>>,
tag: Option<String>,
}
impl ThreadJob {
pub fn new(signals: Signals) -> Self {
pub fn new(signals: Signals, tag: Option<String>) -> Self {
ThreadJob {
signals,
pids: Arc::new(Mutex::new(HashSet::default())),
tag,
}
}
@ -197,10 +203,25 @@ impl Job {
Job::Frozen(frozen_job) => frozen_job.kill(),
}
}
pub fn tag(&self) -> Option<&String> {
match self {
Job::Thread(thread_job) => thread_job.tag.as_ref(),
Job::Frozen(frozen_job) => frozen_job.tag.as_ref(),
}
}
pub fn assign_tag(&mut self, tag: Option<String>) {
match self {
Job::Thread(thread_job) => thread_job.tag = tag,
Job::Frozen(frozen_job) => frozen_job.tag = tag,
}
}
}
pub struct FrozenJob {
pub unfreeze: UnfreezeHandle,
pub tag: Option<String>,
}
impl FrozenJob {

View File

@ -182,12 +182,18 @@ impl PostWaitCallback {
PostWaitCallback(Box::new(f))
}
/// Creates a PostWaitCallback that checks creates a frozen job in the job table
/// Creates a PostWaitCallback that creates a frozen job in the job table
/// if the incoming wait status indicates that the job was frozen.
///
/// If `child_pid` is provided, the returned callback will also remove
/// it from the pid list of the current running job.
pub fn for_job_control(engine_state: &EngineState, child_pid: Option<u32>) -> Self {
///
/// The given `tag` argument will be used as the tag for the newly created job table entry.
pub fn for_job_control(
engine_state: &EngineState,
child_pid: Option<u32>,
tag: Option<String>,
) -> Self {
let this_job = engine_state.current_thread_job.clone();
let jobs = engine_state.jobs.clone();
let is_interactive = engine_state.is_interactive;
@ -200,7 +206,7 @@ impl PostWaitCallback {
if let ForegroundWaitStatus::Frozen(unfreeze) = status {
let mut jobs = jobs.lock().expect("jobs lock is poisoned!");
let job_id = jobs.add_job(Job::Frozen(FrozenJob { unfreeze }));
let job_id = jobs.add_job(Job::Frozen(FrozenJob { unfreeze, tag }));
if is_interactive {
println!("\nJob {} is frozen", job_id.get());