Inter-Job direct messaging (#15253)

# Description

This PR implements an experimental inter-job communication model,
through direct message passing, aka "mail"ing or "dm"ing:



- `job send <id>`: Sends a message the job with the given id, the root
job has id 0. Messages are stored in the recipient's "mailbox"
- `job recv`: Returns a stored message, blocks if the mailbox is empty
- `job flush`: Clear all messages from mailbox

Additionally, messages can be sent with a numeric tag, which can then be
filtered with `mail recv --tag`.
This is useful for spawning jobs and receiving messages specifically
from those jobs.

This PR is mostly a proof of concept for how inter-job communication
could look like, so people can provide feedback and suggestions

Closes  #15199

May close #15220 since now jobs can access their own id.

# User-Facing Changes

Adds, `job id`, `job send`, `job recv` and `job flush`  commands.

# Tests + Formatting

[X] TODO:  Implement tests
[X] Consider rewriting some of the job-related tests to use this, to
make them a bit less fragile.

# After Submitting
This commit is contained in:
Renan Ribeiro
2025-04-26 12:24:35 -03:00
committed by GitHub
parent 0389815137
commit 2d868323b6
14 changed files with 853 additions and 47 deletions

View File

@ -1370,7 +1370,7 @@ On Windows, this would be %USERPROFILE%\AppData\Roaming"#
#[error("Job {id} is not frozen")]
#[diagnostic(
code(nu::shell::os_disabled),
code(nu::shell::job_not_frozen),
help("You tried to unfreeze a job which is not frozen")
)]
JobNotFrozen {
@ -1379,6 +1379,27 @@ On Windows, this would be %USERPROFILE%\AppData\Roaming"#
span: Span,
},
#[error("The job {id} is frozen")]
#[diagnostic(
code(nu::shell::job_is_frozen),
help("This operation cannot be performed because the job is frozen")
)]
JobIsFrozen {
id: usize,
#[label = "This job is frozen"]
span: Span,
},
#[error("No message was received in the requested time interval")]
#[diagnostic(
code(nu::shell::recv_timeout),
help("No message arrived within the specified time limit")
)]
RecvTimeout {
#[label = "timeout"]
span: Span,
},
#[error(transparent)]
#[diagnostic(transparent)]
ChainedError(ChainedError),