Logical State
Logical state is the part of an item that is:
- Implementor / user definable
- Controllable by automation
- Deterministic
Uses
There are three uses of logical state:
- Representing current state.
- Representing goal state.
- Computing state difference.
let params = data.params();
// `dest` references the actual item that is being managed.
// e.g. calculate content hash of actual file being written to.
let state_current = params.dest().read();
// `src` references the *specification* of what the item is intended to be.
// e.g. retrieve content hash from a source file.
let state_goal = params.src().read();
// We can only compute the `diff` when both `src` and `dest` are available.
let state_diff = state_goal - state_current;
Discovery Constraints
In an item's parameters, there must be the following categories of information:
-
src: information of what the item should be, or where to look up that information.Thus,
srcis a reference to where to look upstate_goal. -
dest: reference to where the actual item should be.destis a reference to where to pushstate_current.
Both src and dest may reference resources that are ensured by predecessor items. Meaning sometimes state_goal and state_current cannot be discovered because they rely on the predecessors' completions.
Examples
- A list of files in a zip file cannot be read, if the zip file is not downloaded.
- A file on a server cannot be read, if the server doesn't exist.
- A server cannot have a domain name assigned to it, if the server doesn't exist.
Implications
-
If
destis not available, thenstate_currentmay simply be "does not exist". -
If
srcis not available, and we want to showstate_goalthat is not just "we can't look it up", thensrcmust be defined in terms of something readable during discovery. -
If that is not possible, or is too expensive, then one or more of the following has to be chosen:
-
Item::state_goalfunctions have to always cater forsrcnot being available.It incurs mental effort to always cater for
srcnot being available – i.e. implementing an item would need knowledge beyond itself. -
the
peaceframework defaults to not runningstate_current_fnfor items that have a logical dependency on things thatItem::apply_checkreturnsExecRequiredFor this to work, when the current state is requested,
peacewill:- For each non-parent item, run
state_current,state_goal,state_diff, andapply_check. - If
apply_checkreturnsApplyCheck::ExecNotRequired, then successor items can be processed as well.
- For each non-parent item, run
-
state_currentcould returnResult<Option<Status>, E>:-
Ok(None): State cannot be discovered, likely because predecessor hasn't run -
Ok(Some(State<_, _>)): State cannot be discovered. -
Err(E): An error happened when discovering state.May be difficult to distinguish some cases from
Ok(None), e.g. failed to connect to server, is it because the server doesn't exist, or because the address is incorrect.Should we have two
state_currents? Or pass in whether it's being called fromDiscovervsEnsure– i.e. some information that says "err when failing to connect because the predecessor has been ensured".
-
Option 2 may be something we have to do anyway – we will not be able to provide current state to run
Item::applyfor successors for the same reason.Option 3 may coexist with option 2.
Note: State discovery may be expensive, so it is important to be able to show a stored copy of what is discovered.
-