Skip to main content

Queue

Struct Queue 

Source
pub struct Queue { /* private fields */ }
Expand description

A queue on disk.

Implementations§

Source§

impl Queue

Source

pub fn open() -> Self

The operator’s queue, <home>/queue.

Source

pub fn at(root: PathBuf) -> Self

A queue at an explicit root. Tests use this; so could an operator who wants a queue per project.

Source

pub fn root(&self) -> &Path

Directory holding the task files.

Source

pub fn path_of(&self, id: &str) -> PathBuf

Path for one task id.

Source

pub fn put(&self, task: &mut Task) -> Result<()>

Write a task, atomically, so a daemon killed mid-write leaves the previous state readable rather than a truncated file.

Source

pub fn get(&self, id: &str) -> Result<Task>

Load a task by id or unambiguous id prefix.

Source

pub fn remove( &self, id: &str, in_flight: bool, questions: &Questions, ) -> Result<Removal>

Remove a task, and the claim lock that belongs to it.

in_flight comes from the caller — a live daemon’s heartbeat naming this task — because the task’s own running status cannot answer the question. A daemon killed mid-competition leaves the status at running and an orphaned .lock behind, and a guard that trusted either would make the task undeletable for good: the phone showed exactly that, refusing a task whose daemon had been gone for an hour.

So the lock is removed with the task rather than respected. Any lock still there once no live daemon claims the task is by definition stale, and leaving it would make a deleted task look claimed to Queue::claim and to whoever reads the directory.

Anything still blocked on the id just deleted is quarantined to a machine hold in the same call - see Removal::quarantined - rather than left to wait on a dependency that no longer exists. Best-effort: a dependent claimed by something else right now, or one whose write fails, is simply left for crate::daemon::resolve_blockers’s own poll (or crate::triage::run_once) to catch on its own next pass, and does not fail this removal.

questions is the store missing_blockers checks a blocked_by id against before calling it gone - the same store the caller already resolves id’s own home from, passed in rather than reopened here so a test queue at an explicit root is never quarantined against the operator’s real questions directory.

Source

pub fn list(&self) -> Vec<Task>

Every task on disk, highest priority first and newest first within a priority. This is what magi task list and GET /api/queue print, so a raised priority has to move a task here the moment it is saved, not only in Queue::next_runnable’s own ordering - the operator reading the backlog and the loop about to drain it must agree on what “first” means. Every existing task defaults to priority 0, so this is a no-op change from the old newest-first order for a queue nobody has reprioritised.

Unreadable files are skipped rather than fatal: one corrupt task must not take the queue - or the web UI, or an unattended daemon - down with it.

Source

pub fn superseded(&self) -> HashMap<String, String>

Runs that a later attempt at the same task replaced, mapped to the id of the attempt that replaced them.

A task keeps its attempts in order, and the deck showed them as two cards with the same title and no hint which was which: yukimemi asked why stalled and blocked appeared twice for one task, and the answer - “those are two tries, and the second one exists because of a bug since fixed” - was not on the screen anywhere.

Read from the queue rather than stored on the run, because the ordering is the queue’s fact: a RunState has no idea another attempt happened after it.

Source

pub fn superseded_by(&self, run: &str) -> Option<String>

Whether run is an earlier attempt a later one replaced, and if so the id of that later attempt.

Same walk as Queue::superseded, narrowed to one run: a run detail page asks about exactly one run at a time, and this keeps that call site from building (and discarding) the whole map’s HashMap just to read one entry out of it.

Source

pub fn latest_attempt(&self, run: &str) -> Option<String>

The task’s own most recent attempt, when run belongs to that task but is not already that attempt.

Distinct from Queue::superseded_by, which names only the very next attempt: a chain of retries (A superseded by B superseded by C) leaves an older run pointing at an intermediate one that may itself be unresolved, and a run’s own detail page needs to know where the task’s story currently stands - the chain’s current head, C - not an attempt in the middle of it that a client would otherwise have to walk to by hand.

Source

pub fn next_runnable(&self) -> Option<Task>

The task a daemon should run next, or None when the queue is idle.

Highest priority first, oldest first within a priority, so a burst of agent-filed work cannot starve the task a human filed this morning.

Source

pub fn claim(&self, id: &str) -> Result<Claim>

Take exclusive ownership of a task.

The lock is a create_new file next to the task, which is atomic on every platform magi targets. It exists so two daemons - or a daemon and a human running magi run - cannot drive one task into two competing runs. The returned guard releases on drop, including on panic.

Source

pub fn resolve_id(&self, prefix: &str) -> Result<String>

Expand an id prefix to exactly one task id.

Source

pub fn revision(&self) -> u64

Change detection token for the queue.

Combines file names and modification times of all task files in the queue, so adding, modifying, or deleting any task — even an older one — moves the revision and notifies connected clients via the change stream. Returns 0 when the queue is completely empty.

Trait Implementations§

Source§

impl Clone for Queue

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Queue

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl Freeze for Queue

§

impl RefUnwindSafe for Queue

§

impl Send for Queue

§

impl Sync for Queue

§

impl Unpin for Queue

§

impl UnsafeUnpin for Queue

§

impl UnwindSafe for Queue

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more