party_run/
schdeuler.rs

1//! Batch command scheduler
2use crate::party_command::PartyCommand;
3
4/// Alias for a vector of Party commands
5pub type CommandBatch = Vec<PartyCommand>;
6
7/// Schedule a vector of Party commands into batches.
8/// If a series of commands have the parallel flag set to `true`
9/// they are batched together and will be run in parallel.
10/// Commands that have the parallel flag set to `false` will be put into
11/// their own batches of size 1.
12pub fn schedule_commands(commands: Vec<PartyCommand>) -> Vec<CommandBatch> {
13    let mut batches = vec![];
14
15    let mut batch = vec![];
16    for command in commands {
17        if command.is_parallel {
18            batch.push(command);
19        } else {
20            // If there is at least a command in the current batch push it
21            if !batch.is_empty() {
22                batches.push(batch);
23            }
24
25            // Push the current command alone
26            batches.push(vec![command]);
27
28            // Prepare the new batch
29            batch = vec![];
30        }
31    }
32
33    // Push the last batch if not empty
34    if !batch.is_empty() {
35        batches.push(batch);
36    }
37
38    batches
39}
40
41#[cfg(test)]
42pub mod test {
43    use crate::party_command::PartyCommand;
44
45    use super::schedule_commands;
46
47    fn parallel_command() -> PartyCommand {
48        PartyCommand::new("".into(), vec![], true)
49    }
50
51    fn sequential_command() -> PartyCommand {
52        PartyCommand::new("".into(), vec![], false)
53    }
54
55    #[test]
56    fn test_scheduler_ending_with_sequential() {
57        // GIVEN
58        let commands = vec![
59            parallel_command(),
60            parallel_command(),
61            sequential_command(),
62            parallel_command(),
63            parallel_command(),
64            parallel_command(),
65            sequential_command(),
66            sequential_command(),
67        ];
68
69        // WHEN
70        let batches = schedule_commands(commands);
71
72        // THEN
73        assert_eq!(batches.len(), 5);
74        assert_eq!(batches[0].len(), 2);
75        assert_eq!(batches[1].len(), 1);
76        assert_eq!(batches[2].len(), 3);
77        assert_eq!(batches[3].len(), 1);
78        assert_eq!(batches[4].len(), 1);
79    }
80
81    #[test]
82    fn test_scheduler_ending_with_parallel() {
83        // GIVEN
84        let commands = vec![
85            parallel_command(),
86            parallel_command(),
87            sequential_command(),
88            parallel_command(),
89            parallel_command(),
90            parallel_command(),
91        ];
92
93        // WHEN
94        let batches = schedule_commands(commands);
95
96        // THEN
97        assert_eq!(batches.len(), 3);
98        assert_eq!(batches[0].len(), 2);
99        assert_eq!(batches[1].len(), 1);
100        assert_eq!(batches[2].len(), 3);
101    }
102}