ProjectError#

The reason a Project call doesn't fit the project's current state: there's no solved baseline, a baseline_id token is out of date, or the project needs a full reload. It reaches you wrapped in Error::Project. The project's state is unchanged when the call fails.

Declaration#

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProjectError {
    NoBaseline,
    StaleBaseline,
    NeedsResync,
}

impl std::error::Error for ProjectError {}
impl std::fmt::Display for ProjectError {}

ProjectError is Copy and PartialEq, so it can be compared with ==. With the serde feature it also implements Serialize and Deserialize, as the same kebab-case strings that Display prints.

Variants#

Variant Display When it occurs
NoBaseline no-baseline The project has no accepted baseline: it was never solved, or it was edited with apply after the last solve. Returned by preview, load_profile, evaluate, evaluate_with, suggest_assignments and roster.
StaleBaseline stale-baseline A baseline_id passed to the call doesn't name the current accepted baseline, including when the project is unsolved. Returned by preview (options or changes token), apply (changes token), evaluate and evaluate_with (options token or any candidate's changes token), suggest_assignments and load_profile (options token).
NeedsResync needs-resync An earlier apply rejected at least one operation, so the stored data may no longer match the caller's. Returned by solve(None), apply and level until solve(Some(data)) replaces the data.

On calls that can return both NoBaseline and StaleBaseline, the baseline is checked first: an unsolved project gives NoBaseline even when a token is also passed.

Take the token from the latest solve result. See Project for which result carries baseline_id.

MatchError::Project from slots wraps the same type. See MatchError.

Example#

use plen_core::{Error, Project, ProjectError, SchedulingChanges};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut project = Project::default();

    // The token doesn't name the current baseline (the project has none).
    let changes = SchedulingChanges {
        baseline_id: Some("outdated-token".to_string()),
        ..Default::default()
    };

    match project.apply(&changes) {
        Ok(report) => println!("{} operations applied", report.applied.len()),
        Err(Error::Project(ProjectError::StaleBaseline)) => println!("re-read the baseline and retry"),
        Err(Error::Project(ProjectError::NeedsResync)) => println!("reload with solve(Some(data))"),
        Err(e) => return Err(e.into()),
    }
    Ok(())
}

For recovery patterns, see Error handling.