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


# Pool

The workers that may be assigned, each a project resource with its skills. A `Pool` is the second argument of [`slots`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/slots.md>). Build it with a struct literal, or start from `Pool::default()` (no workers). The pool isn't stored in the project: pass it again on every `slots` call.

## Declaration

```rust
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Pool {
    pub workers: Vec<Worker>,
}
```

## Fields

### workers

```rust
pub workers: Vec<Worker>
```

The candidate workers, one [`Worker`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/worker.md>) per resource. The order is the tie-break preference: a slot's [`allowed`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/suggest/slot.md>) list keeps the matching workers in pool order. A resource missing from the pool is never a candidate.

Default: empty.

## Errors

[`slots`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/slots.md>) checks the pool before the requirements and returns `Err(`[`MatchError::Invalid`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/match-error.md>)`)` with the path below.

| When it occurs | Path |
|---|---|
| the worker's resource isn't a resource of the project | `pool.workers[i].resource` |
| two workers name the same resource (ids compare by [`Id`](<https://docs.dhtmlx.com/planning-engine/rust/api/core/data/id.md>) key) | `pool.workers[i].resource` |

Errors in a worker's skill list are on [`Worker`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/worker.md>).

## Example

```rust
use plen_assign::{slots, Pool, Requirement, Skill, SkillMatch, Worker};
use plen_core::{DateTime, Project, ProjectData, ResourceData, SolveOptions, TaskData};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut task = TaskData::new("api");
    task.start_date = DateTime::from_ymd_hm(2026, 8, 10, 8, 0);
    task.duration = Some(2.0);
    let data = ProjectData {
        tasks: vec![task],
        resources: ["ann", "bob"]
            .map(|id| ResourceData { id: id.into(), capacity: None, calendar_id: None })
            .to_vec(),
        ..Default::default()
    };
    let mut project = Project::default();
    project.solve(Some(data), &SolveOptions::default())?;

    // "bob" comes first, so he is preferred on ties.
    let pool = Pool {
        workers: vec![
            Worker { resource: "bob".into(), skills: vec![Skill { id: "backend".into(), value: 1.0 }] },
            Worker { resource: "ann".into(), skills: vec![Skill { id: "backend".into(), value: 1.0 }] },
        ],
    };
    let requirements = [Requirement::new("be", "api", vec![SkillMatch::at_least("backend", 1.0)])];

    for slot in slots(&project, &pool, &requirements)? {
        let allowed: Vec<String> = slot.allowed.iter().map(|id| id.to_string()).collect();
        println!("{}: {allowed:?}", slot.id);
    }
    Ok(())
}
```

Output:

```text
be#1: ["bob", "ann"]
```

## Related

- [`Worker`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/worker.md>) - one entry of the pool
- [`Requirement`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/requirement.md>) - the requirements matched against the pool's workers
- [`slots`](<https://docs.dhtmlx.com/planning-engine/rust/api/assign/slots.md>) - takes the pool and builds the slots
- [Skills and Requirements](<https://docs.dhtmlx.com/planning-engine/rust/resources-and-assignment/skills-and-requirements.md>) - shows how to build a pool of skilled workers
