Skip to main content

Request

Enum Request 

Source
#[non_exhaustive]
pub enum Request {
Show 25 variants Ping, ListFlock, Describe { selector: SelectorSpec, }, Start { apps: Vec<AppConfig>, }, ConfigDrift { apps: Vec<AppConfig>, }, Stop { selector: SelectorSpec, }, Restart { selector: SelectorSpec, }, Reload { selector: SelectorSpec, }, Delete { selector: SelectorSpec, }, Scale { name: String, count: u32, }, SetSmit { sheep: String, smit: Option<Smit>, }, Reopen { selector: SelectorSpec, }, Flush { selector: SelectorSpec, }, Trigger { selector: SelectorSpec, action: String, params: Option<String>, }, Signal { selector: SelectorSpec, signal: String, }, SendLine { selector: SelectorSpec, line: String, }, SaveRoll, Muster, DogConfig { name: String, }, EnableDog { name: String, source: DogSource, }, DisableDog { name: String, }, DogStaleness, HandoverFitness, KillDaemon, Subscribe { topics: Vec<String>, },
}
Expand description

One RPC request

Variants (Non-exhaustive)§

This enum is marked as non-exhaustive
Non-exhaustive enums could have additional variants added in future. Therefore, when matching against variants of non-exhaustive enums, an extra wildcard arm must be added to account for any future variants.
§

Ping

Liveness check

§

ListFlock

Full flock listing

§

Describe

Detailed info for matching sheep

Fields

§selector: SelectorSpec

Which sheep

§

Start

Register + start apps

Fields

§apps: Vec<AppConfig>

App configs — the daemon MUST re-normalize (peer input is untrusted); failures return RpcErrorCode::InvalidConfig

§

ConfigDrift

Ask which of apps name a sheep the flock already has under a different config

Read-only: nothing is registered, started, or changed. Self::Start on an already-registered name adds instances rather than reconciling config, which is what shep stock relies on; this is how a caller finds out that an edit it just read from a Flockfile is one Start will not apply, instead of the edit vanishing without a word.

Answers Response::Drifted with one SheepDrift per app that is both registered and different. An app the flock does not have is absent from the answer, not reported as unchanged: Start will register it, so there is nothing to warn about.

Fields

§apps: Vec<AppConfig>

The configs to compare against, exactly as Self::Start would carry them. The daemon MUST re-normalize (peer input is untrusted, and an unnormalized config would report every default it has not spelled out as a difference); failures return RpcErrorCode::InvalidConfig.

§

Stop

Stop matching sheep (stay registered)

Fields

§selector: SelectorSpec

Which sheep

§

Restart

Restart matching sheep

Fields

§selector: SelectorSpec

Which sheep

§

Reload

Replace each matching sheep with a fresh instance of the same app, one instance of an app at a time, so the app has a window in which it can stay reachable across the swap

Fields

§selector: SelectorSpec

Which sheep. No default anywhere in the stack — a reload replaces running processes, so the operator names the target, exactly as stop/restart/delete do (see shep reload).

§

Delete

Stop + deregister matching sheep

Fields

§selector: SelectorSpec

Which sheep

§

Scale

Set how many instances one app runs (see shep stock).

§Why a name and not a selector

Every other verb here takes a SelectorSpec, and this one deliberately does not. instances is a per-app number and instance slots are allocated against the same-name group (shep_daemon::assemble::instance_slots), so a selector matching two apps would have to mean either “four of each” or “four in total”, and neither reading is more obviously right than the other. A name has one meaning.

§Why absolute and not a delta

There is no +N/-N form and there will not be one. An absolute count is idempotent — run it twice, get the same flock — where two operators sending +2 against the same app get a number neither of them asked for. This project’s own trace notes also record a crash on pm2’s relative-remove path, and those notes exist so shep does not reproduce what they record.

Fields

§name: String

The app’s name, exactly as its config spells it. Not a selector: no all, no regex, no fold:.

§count: u32

How many instances the app has when this returns. 0 is refused with RpcErrorCode::InvalidConfignormalize rejects instances == 0 for every other path into the daemon, and shep delete is the verb for removing an app.

§

SetSmit

Attach a short marker to sheep for shep flock to paint, or clear it with None.

By NAME rather than a selector, for Self::Scale’s reason (see its own doc above): a smit belongs to a sheep, not to one of its instances, and every instance of that name shows it — including one spawned after the smit was painted.

Held in memory and scoped to the connection that sent it. When that connection closes, for any reason, the smits it painted go with it. A publisher therefore republishes rather than publishing on change.

shep does not parse it and has no opinion about what it means.

Fields

§sheep: String

Which sheep.

§smit: Option<Smit>

The marker, or None to clear it.

§

Reopen

Reopen every matched sheep’s log files, for an external rotator that has renamed them (create-mode rotation)

Fields

§selector: SelectorSpec

Which sheep

§

Flush

Empty every matched sheep’s log files: flush what is still pending, then truncate the recorded paths

Fields

§selector: SelectorSpec

Which sheep. No default anywhere in the stack — this destroys log data, so the operator names the target (see shep flush).

§

Trigger

Send a named action to every matched sheep over its shepherd channel and report what each app says back (see shep trigger).

Fields

§selector: SelectorSpec

Which sheep. No default anywhere in the stack, matching stop/restart/reload/delete/flush: an operator names the target rather than trigger an action against the whole flock by accident.

§action: String

The action name. Free-form — the daemon never declares, parses, or validates it; an app that does not recognize the name is expected to say so in its own reply rather than stay silent.

§params: Option<String>

Argument text for the action, passed through to the app verbatim. One opaque string, not structured data: the daemon holds no schema for it, matching the shepherd channel’s own action message this ultimately becomes.

§

Signal

Deliver one signal to every matched sheep’s OWN process — never its process group (see shep signal).

Fields

§selector: SelectorSpec

Which sheep. No default anywhere in the stack, matching every other verb that reaches a running process: an operator names the target rather than signal the whole flock by accident.

§signal: String

The signal’s name, as OperatorSignal spells it — the SIG prefix and the case are both optional.

A String rather than the enum, for the reason AppConfig::kill_signal is one: the wire stays plain text a person can read in a capture, and the daemon re-validates regardless, because peer input is untrusted. A name outside the grammar answers RpcErrorCode::InvalidConfig.

§

SendLine

Write one line to every matched sheep’s stdin (see shep whisper).

Fields

§selector: SelectorSpec

Which sheep. No default, matching every other verb that reaches a running process.

§line: String

The line, WITHOUT its terminator — the shepherd appends exactly one \n when it writes. Carrying the terminator here would leave “did the caller include one” as a question every hop has to re-answer, and a caller that included two would send an empty line the app never asked for.

A line containing an embedded newline is refused (RpcErrorCode::InvalidConfig): it would deliver two commands where the operator typed one.

§

SaveRoll

Write the muster roll now, bypassing the snapshot writer’s debounce

§

Muster

Assemble the flock from the muster roll on disk: start every app the roll recorded running, leaving every app the flock already has exactly as it stands

§

DogConfig

Ask for one dog’s [dog.<name>] section, as the dog itself parses it

Fields

§name: String

The dog’s name — the config key, not a selector

§

EnableDog

Start one dog now, marking it as coming from source

Fields

§name: String

The dog’s name

§source: DogSource

Where its binary comes from

§

DisableDog

Stop and deregister one dog

Answers Response::Deleted, the same reply Delete gives: disabling deregisters exactly as Delete does, so this is the same fact and not a coincidence of shape. A variant of its own (DogDisabled, say) would carry nothing Deleted does not.

Fields

§name: String

The dog’s name

§

DogStaleness

Ask which dogs this daemon has given up on, and which it is still waiting to hear from (shep daemon reload, the handover design’s G13).

Read-only, and about THIS daemon’s own handshakes. A dog’s recorded crate version describes the process that was running when it connected, so it says nothing about a dog that has since been replaced; the only thing that knows whether a dog can talk to this daemon is whether this daemon accepted its handshake. That is what this answers, which is why the reading is worth taking AFTER a reload rather than before one.

Answers Response::DogStaleness.

§Why this variant does not move PROTOCOL_VERSION

The same argument Self::HandoverFitness makes above, and the same gate enforces it: its only caller is shep daemon reload, which asks it of the successor it has just proven is running this binary’s own version. An older daemon is never sent it.

§

HandoverFitness

Ask whether this daemon could hand its flock to a successor in place, rather than stopping it and starting it again (shep daemon reload).

Read-only, and nothing here triggers a handover. The trigger is a signal and always was: a socket request cannot be the trigger, because the case that most needs a reload is the one where the daemon refuses the client at the handshake. What travels over the socket is the DECISION, for a reason a signal cannot serve (spec H3a) – a signal carries no reply, so a daemon that took one, refused, and fell back to its own graceful stop would leave the client polling for a successor nobody started, with the flock down and staying down.

Answers Response::HandoverFitness. Every refusal is a feature the running daemon cannot yet carry, not an error: the caller falls back to a stop-and-start, which is correct behaviour rather than a degraded one, and prints the reason to the operator who asked for the reload.

§Why this variant does not move PROTOCOL_VERSION

An older daemon cannot deserialize a variant it has never seen, which is normally what a bump is for. It is never sent to one. daemon reload is an exempt verb, so it connects to a mismatched daemon deliberately, learns the daemon’s crate version from the handshake, and takes the stop arm for anything predating the handover without ever asking. shep-cli’s commands::daemon holds that gate and a test of its own pins it.

§

KillDaemon

Graceful daemon shutdown

§

Subscribe

Subscribe this connection to bus topics (glob patterns)

Fields

§topics: Vec<String>

Topic globs, e.g. process.*

Trait Implementations§

Source§

impl Clone for Request

Source§

fn clone(&self) -> Request

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 Request

Source§

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

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Request

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl PartialEq for Request

Source§

fn eq(&self, other: &Request) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl Serialize for Request

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl StructuralPartialEq for Request

Auto Trait Implementations§

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> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

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

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

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> 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, <T as TryFrom<U>>::Error>

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.