[Canonical page](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/schedule/>)
[Full documentation index](<https://docs.dhtmlx.com/planning-engine/llms.txt>)


# schedule

Schedules a [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) snapshot once and returns the result. The call is stateless: it's equivalent to `Project::default().solve(Some(data), options)` on a temporary [`Project`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md>) that's dropped when the call returns. Nothing is kept between calls.

## Signature

```rust
pub fn schedule(data: ProjectData, options: &SolveOptions) -> Result<ScheduleResult, Error>
```

Synchronous and CPU-only. The same `data` and `options` always produce the same result.

## Parameters

| Name | Type | Description |
|---|---|---|
| `data` | [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>) | The full snapshot to schedule. Taken by value. |
| `options` | [`&SolveOptions`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/solve-options.md>) | What to schedule and what to report. `&SolveOptions::default()` schedules the whole project. |

`data` is always validated with [`Validation::Strict`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/validation.md>). 

## Returns

`Ok(`[`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>)`)`, returned by value.

The result's `baseline_id` is set, but it names the baseline of the temporary project, so no later call can use it.

## Errors

| Error | When it occurs |
|---|---|
| [`Error::Input`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/error.md>) | `data` fails strict validation; see [`InputError`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error.md>). The rules are listed on [`ProjectData`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/project-data.md>). |

`schedule` never returns `Error::Project`: each call starts from a fresh project.

## Example

```rust
use plen_core::{schedule, DateTime, LinkData, LinkType, ProjectData, SolveOptions, TaskData};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let monday = DateTime::from_ymd_hm(2026, 1, 5, 8, 0).ok_or("invalid date")?;

    let mut design = TaskData::new("design");
    design.start_date = Some(monday);
    design.duration = Some(2.0);

    let mut build = TaskData::new("build");
    build.start_date = Some(monday);
    build.duration = Some(3.0);

    let data = ProjectData {
        tasks: vec![design, build],
        links: vec![LinkData {
            id: "l1".into(),
            source: "design".into(),
            target: "build".into(),
            link_type: LinkType::Fs,
            lag: 0.0,
            lag_unit: None,
        }],
        ..Default::default()
    };

    let result = schedule(data, &SolveOptions::default())?;

    for update in &result.updates {
        if let (Some(start), Some(end)) = (update.start_date, update.end_date) {
            println!("{}: {} - {}", update.id, start, end);
        }
    }
    Ok(())
}
```

## Related

- [`Project::solve`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/project/project.md#solve>) - the stateful equivalent that keeps the baseline
- [`ScheduleResult`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/results/schedule-result.md>) - the returned result
- [`InputError`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/errors/input-error.md>) - what strict validation reports
- [Scheduling a Project](<https://docs.dhtmlx.com/planning-engine/rust/scheduling/scheduling-a-project.md#one-shot-scheduling>) - when to use one-shot scheduling
- [Quick start](<https://docs.dhtmlx.com/planning-engine/rust/quick-start.md>) - a first schedule end to end
