7
7
[ ![ License] ( https://img.shields.io/badge/license-Apache-green.svg )] ( LICENSE-APACHE )
8
8
[ ![ License] ( https://img.shields.io/badge/license-MIT-green.svg )] ( LICENSE-MIT )
9
9
10
- ` future_queue ` is a variant of
11
- [ ` buffer_unordered ` ] ( https://docs.rs/futures/latest/futures/stream/trait.StreamExt.html#method.buffer_unordered ) ,
12
- where each future can be assigned a different weight.
10
+ ` future_queue ` provides ways to run several futures:
11
+ * concurrently
12
+ * in the order they're spawned
13
+ * with global limits
14
+ * and with an optional group specified for each future, with its own limits.
13
15
14
16
This crate is part of the [ nextest organization] ( https://github.com/nextest-rs ) on GitHub, and is
15
17
designed to serve the needs of [ cargo-nextest] ( https://nexte.st ) .
@@ -33,17 +35,24 @@ Common use cases for `buffer_unordered` include:
33
35
34
36
` buffer_unordered ` works well for many use cases. However, one issue with it is that it treats
35
37
all futures as equally taxing: there's no way to say that some futures consume more resources
36
- than others. For nextest in particular, some tests can be much heavier than others, and fewer of
37
- those tests should be run simultaneously.
38
+ than others, or that some subsets of futures should be mutually excluded from others.
39
+
40
+ For nextest in particular, some tests can be much heavier than others, and fewer of those tests
41
+ should be run simultaneously. Also, some tests need to be mutually excluded from others, or
42
+ other concurrency limits placed on them.
38
43
39
44
[ ^ 1 ] : This adaptor takes a stream of futures for maximum generality. In practice this is often
40
45
an * iterator* of futures, converted over using
41
46
[ ` stream::iter ` ] ( https://docs.rs/futures/latest/futures/stream/fn.iter.html ) .
42
47
43
48
## About this crate
44
49
45
- This crate provides an adaptor on streams called ` future_queue ` , which can run
46
- several futures simultaneously, limiting the concurrency to a maximum * weight* .
50
+ This crate provides two adaptors on streams.
51
+
52
+ ### 1. The ` future_queue ` adaptor
53
+
54
+ The [ ` future_queue ` ] ( StreamExt::future_queue ) adaptor can run several futures simultaneously,
55
+ limiting the concurrency to a maximum * weight* .
47
56
48
57
Rather than taking a stream of futures, this adaptor takes a stream of ` (usize, future) ` pairs,
49
58
where the ` usize ` indicates the weight of each future. This adaptor will schedule and buffer
@@ -57,16 +66,11 @@ Note that in some cases, the current weight may exceed the maximum weight. For e
57
66
* If the next future has weight ** 6** , then it will be scheduled and the current weight will become ** 26** .
58
67
* No new futures will be scheduled until the current weight falls to ** 23** or below.
59
68
60
- It is possible to have a variant of this adaptor which always stays below the limit and holds
61
- the next future in abeyance; however, the implementation for that variant is a bit more
62
- complicated, and is also not the behavior desired by nextest. This variant may be provided in
63
- the future.
64
-
65
69
The weight of a future can be zero, in which case it doesn't count towards the maximum weight.
66
70
67
71
If all weights are 1, then ` future_queue ` is exactly the same as ` buffer_unordered ` .
68
72
69
- ## Examples
73
+ #### Examples
70
74
71
75
``` rust
72
76
use futures :: {channel :: oneshot, stream, StreamExt as _};
@@ -87,6 +91,41 @@ assert_eq!(queue.next().await, Some(Ok("world")));
87
91
assert_eq! (queue . next (). await , None );
88
92
```
89
93
94
+ ### 2. The ` future_queue_grouped ` adaptor
95
+
96
+ The [ ` future_queue_grouped ` ] ( StreamExt::future_queue_grouped ) adaptor is like ` future_queue ` ,
97
+ except it is possible to specify an optional * group* for each future. Each group has a maximum
98
+ weight, and a future will only be scheduled if both the maximum weight and the group weight
99
+ aren't exceeded.
100
+
101
+ The current weight for groups may exceed the maximum weight, similar to ` future_queue ` .
102
+
103
+ #### Examples
104
+
105
+ ``` rust
106
+ use futures :: {channel :: oneshot, stream, StreamExt as _};
107
+ use future_queue :: {StreamExt as _};
108
+
109
+ let (send_one , recv_one ) = oneshot :: channel ();
110
+ let (send_two , recv_two ) = oneshot :: channel ();
111
+
112
+ let stream_of_futures = stream :: iter (
113
+ vec! [
114
+ (1 , Some (" group1" ), recv_one ),
115
+ (2 , None , recv_two ),
116
+ ],
117
+ );
118
+ let mut queue = stream_of_futures . future_queue_grouped (10 , [(" group1" , 5 )]);
119
+
120
+ send_two . send (" hello" )? ;
121
+ assert_eq! (queue . next (). await , Some (Ok (" hello" )));
122
+
123
+ send_one . send (" world" )? ;
124
+ assert_eq! (queue . next (). await , Some (Ok (" world" )));
125
+
126
+ assert_eq! (queue . next (). await , None );
127
+ ```
128
+
90
129
## Minimum supported Rust version (MSRV)
91
130
92
131
The minimum supported Rust version is ** Rust 1.56.**
0 commit comments