Skip to content

Commit a6abe9f

Browse files
committed
Document unlimited builder and reuse test fixtures
1 parent d919416 commit a6abe9f

12 files changed

Lines changed: 67 additions & 59 deletions

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ tracing-subscriber = "0.3"
3838
metrics = { version = "0.24.2", optional = true }
3939
metrics-exporter-prometheus = { version = "0.17.2", optional = true, features = ["http-listener"] }
4040
thiserror = "2.0.12"
41+
static_assertions = "1"
4142

4243
[dev-dependencies]
4344
rstest = "0.26.1"

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,14 +159,26 @@ let (dlq_tx, _dlq_rx) = mpsc::channel(8);
159159
let (_queues, _handle) = PushQueues::<u8>::builder()
160160
.high_capacity(8)
161161
.low_capacity(8)
162-
.rate(Some(100)) // pass None to disable rate limiting
162+
.rate(Some(100))
163163
.dlq(Some(dlq_tx)) // frames drop if the DLQ is absent or full
164164
.build()
165165
.expect("failed to build PushQueues");
166166
# drop((_queues, _handle));
167167
# }
168168
```
169169

170+
Disable throttling with the `unlimited` convenience:
171+
172+
```rust,no_run
173+
use wireframe::push::PushQueues;
174+
let (_queues, _handle) = PushQueues::<u8>::builder()
175+
.high_capacity(8)
176+
.low_capacity(8)
177+
.unlimited()
178+
.build()
179+
.expect("failed to build PushQueues");
180+
```
181+
170182
## Connection Lifecycle
171183

172184
Protocol callbacks are consolidated under the `WireframeProtocol` trait,

docs/multi-packet-and-streaming-responses-design.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ The public API is designed for clarity, performance, and ergonomic flexibility.
7373
The `Response` enum is the primary return type for all handlers. It is enhanced
7474
to provide optimized paths for common response patterns.
7575

76-
```Rust
76+
```rust
7777
use futures_core::stream::Stream;
7878
use std::pin::Pin;
7979

@@ -109,7 +109,7 @@ To enable more robust error handling, a generic error enum will be introduced.
109109
This allows the framework and protocol implementations to distinguish between
110110
unrecoverable transport failures and logical, protocol-level errors.
111111

112-
```Rust
112+
```rust
113113
/// A generic error type for wireframe operations.
114114
#
115115
pub enum WireframeError<E> {
@@ -139,7 +139,7 @@ The following examples illustrate how developers will use the new API.
139139

140140
Existing code continues to work without modification, fulfilling goal **G4**.
141141

142-
```Rust
142+
```rust
143143
async fn handle_ping(_req: Request) -> Result<Response<MyFrame, MyError>, MyError> {
144144
// `MyFrame` implements `Into<Response<...>>`
145145
Ok(build_pong_frame().into())
@@ -151,7 +151,7 @@ async fn handle_ping(_req: Request) -> Result<Response<MyFrame, MyError>, MyErro
151151
For simple, fixed-size multi-part responses, like a MySQL result set header,
152152
`Response::Vec` is both ergonomic and performant.
153153

154-
```Rust
154+
```rust
155155
async fn handle_select_headers(_req: Request) -> Result<Response<MySqlFrame, MyError>, MyError> {
156156
// Pre-build frames for: column-count, column-def, EOF
157157
let frames = vec!;
@@ -164,7 +164,7 @@ async fn handle_select_headers(_req: Request) -> Result<Response<MySqlFrame, MyE
164164
For large or dynamically generated result sets, like a PostgreSQL `COPY OUT`
165165
command, `async-stream` provides an intuitive way to generate the stream.
166166

167-
```Rust
167+
```rust
168168
use async_stream::try_stream;
169169

170170
async fn handle_copy_out(req: PgCopyRequest) -> Result<Response<PgFrame, PgError>, PgError> {

src/push/queues/builder.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,24 @@ use super::{
3535
/// let (_queues, _handle) = PushQueues::<u8>::builder()
3636
/// .high_capacity(8)
3737
/// .low_capacity(8)
38-
/// .rate(Some(100)) // pass None to disable rate limiting
38+
/// .rate(Some(100))
3939
/// .dlq(Some(dlq_tx)) // frames are dropped if no DLQ or DLQ is full
4040
/// .build()
4141
/// .expect("failed to build PushQueues");
4242
/// # }
4343
/// ```
4444
///
45+
/// Disable rate limiting with the `unlimited` convenience:
46+
///
47+
/// ```rust,no_run
48+
/// use wireframe::push::PushQueues;
49+
/// let (_queues, _handle) = PushQueues::<u8>::builder()
50+
/// .unlimited()
51+
/// .build()
52+
/// .expect("failed to build PushQueues");
53+
/// # drop((_queues, _handle));
54+
/// ```
55+
///
4556
/// Builders can also be constructed directly:
4657
///
4758
/// ```

src/push/queues/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use std::{
1212
};
1313

1414
use leaky_bucket::RateLimiter;
15+
use static_assertions::const_assert;
1516
use tokio::sync::mpsc;
1617

1718
mod builder;
@@ -38,7 +39,7 @@ const DEFAULT_PUSH_RATE: usize = 100;
3839
pub const MAX_PUSH_RATE: usize = 10_000;
3940

4041
// Compile-time guard: DEFAULT_PUSH_RATE must not exceed MAX_PUSH_RATE.
41-
const _: () = assert!(DEFAULT_PUSH_RATE <= MAX_PUSH_RATE);
42+
const_assert!(DEFAULT_PUSH_RATE <= MAX_PUSH_RATE);
4243

4344
/// Priority level for outbound messages.
4445
#[derive(Clone, Copy, Debug, PartialEq, Eq)]

tests/push.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use wireframe_testing::{push_expect, recv_expect};
2020

2121
#[fixture]
2222
fn queues() -> (PushQueues<u8>, PushHandle<u8>) {
23-
support::builder()
23+
support::builder::<u8>()
2424
.high_capacity(2)
2525
.low_capacity(2)
2626
.rate(Some(1))
@@ -30,7 +30,7 @@ fn queues() -> (PushQueues<u8>, PushHandle<u8>) {
3030

3131
#[fixture]
3232
fn small_queues() -> (PushQueues<u8>, PushHandle<u8>) {
33-
support::builder()
33+
support::builder::<u8>()
3434
.build()
3535
.expect("failed to build PushQueues")
3636
}
@@ -40,29 +40,29 @@ fn small_queues() -> (PushQueues<u8>, PushHandle<u8>) {
4040
#[case::zero(0)]
4141
#[case::too_high(MAX_PUSH_RATE + 1)]
4242
fn builder_rejects_invalid_rate(#[case] rate: usize) {
43-
let result = support::builder().rate(Some(rate)).build();
43+
let result = support::builder::<u8>().rate(Some(rate)).build();
4444
assert!(matches!(result, Err(PushConfigError::InvalidRate(r)) if r == rate));
4545
}
4646

4747
/// Setting the rate to `None` disables throttling without error.
4848
#[test]
4949
fn builder_accepts_none_rate() {
50-
let result = support::builder().rate(None).build();
50+
let result = support::builder::<u8>().rate(None).build();
5151
assert!(result.is_ok(), "builder should accept None rate");
5252
}
5353

5454
/// Builder accepts the maximum supported rate.
5555
#[test]
5656
fn builder_accepts_max_rate() {
57-
let result = support::builder().rate(Some(MAX_PUSH_RATE)).build();
57+
let result = support::builder::<u8>().rate(Some(MAX_PUSH_RATE)).build();
5858
assert!(result.is_ok(), "builder should accept MAX_PUSH_RATE");
5959
}
6060

6161
/// Disabling throttling allows rapid bursts to succeed.
6262
#[tokio::test]
6363
async fn disables_throttling_allows_burst_pushes() {
6464
time::pause();
65-
let (_queues, handle) = support::builder()
65+
let (_queues, handle) = support::builder::<u8>()
6666
.high_capacity(20)
6767
.low_capacity(20)
6868
.unlimited()
@@ -81,19 +81,19 @@ async fn disables_throttling_allows_burst_pushes() {
8181

8282
#[test]
8383
fn builder_rejects_zero_capacity() {
84-
let hi = support::builder().high_capacity(0).build();
84+
let hi = support::builder::<u8>().high_capacity(0).build();
8585
assert!(matches!(
8686
hi,
8787
Err(PushConfigError::InvalidCapacity { high: 0, low: 1 })
8888
));
8989

90-
let lo = support::builder().low_capacity(0).build();
90+
let lo = support::builder::<u8>().low_capacity(0).build();
9191
assert!(matches!(
9292
lo,
9393
Err(PushConfigError::InvalidCapacity { high: 1, low: 0 })
9494
));
9595

96-
let both = support::builder().high_capacity(0).low_capacity(0).build();
96+
let both = support::builder::<u8>().high_capacity(0).low_capacity(0).build();
9797
assert!(matches!(
9898
both,
9999
Err(PushConfigError::InvalidCapacity { high: 0, low: 0 })
@@ -230,7 +230,7 @@ async fn rate_limiter_shared_across_priorities() {
230230
#[tokio::test]
231231
async fn unlimited_queues_do_not_block() {
232232
time::pause();
233-
let (mut queues, handle) = support::builder()
233+
let (mut queues, handle) = support::builder::<u8>()
234234
.unlimited()
235235
.build()
236236
.expect("failed to build PushQueues");
@@ -248,7 +248,7 @@ async fn unlimited_queues_do_not_block() {
248248
#[tokio::test]
249249
async fn rate_limiter_allows_burst_within_capacity_and_blocks_excess() {
250250
time::pause();
251-
let (mut queues, handle) = support::builder()
251+
let (mut queues, handle) = support::builder::<u8>()
252252
.high_capacity(4)
253253
.low_capacity(4)
254254
.rate(Some(3))

tests/push_policies.rs

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,14 @@
22
33
mod support;
44

5-
use futures::future::BoxFuture;
5+
use futures::{FutureExt, future::BoxFuture};
66
use rstest::{fixture, rstest};
77
use serial_test::serial;
88
use tokio::{runtime::Runtime, sync::mpsc};
9-
use futures::FutureExt;
109
use wireframe::push::{PushPolicy, PushPriority, PushQueuesBuilder};
1110
use wireframe_testing::{LoggerHandle, logger};
1211

1312
/// Builds a single-thread [`Runtime`] for async tests.
14-
#[expect(
15-
unused_braces,
16-
reason = "rustc false positive for single line rstest fixtures"
17-
)]
18-
// allow(unfulfilled_lint_expectations): rustc may miss lint for single-line rstest fixtures.
19-
#[allow(unfulfilled_lint_expectations)]
2013
#[fixture]
2114
fn rt() -> Runtime {
2215
tokio::runtime::Builder::new_current_thread()
@@ -25,14 +18,10 @@ fn rt() -> Runtime {
2518
.expect("failed to build test runtime")
2619
}
2720

28-
#[expect(
29-
unused_braces,
30-
reason = "rustc false positive for single line rstest fixtures"
31-
)]
32-
// allow(unfulfilled_lint_expectations): rustc may miss lint for single-line rstest fixtures.
33-
#[allow(unfulfilled_lint_expectations)]
3421
#[fixture]
35-
fn builder() -> PushQueuesBuilder<u8> { support::builder() }
22+
fn builder() -> PushQueuesBuilder<u8> {
23+
support::builder::<u8>()
24+
}
3625

3726
/// Verifies how queue policies log and drop when the queue is full.
3827
#[rstest]

tests/session_registry.rs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,11 @@ use wireframe::{
66
};
77

88
#[fixture]
9-
#[expect(
10-
unused_braces,
11-
reason = "rustc false positive for single-line rstest fixtures"
12-
)]
13-
#[allow(unfulfilled_lint_expectations)]
14-
fn registry() -> SessionRegistry<u8> { SessionRegistry::default() }
9+
fn registry() -> SessionRegistry<u8> {
10+
SessionRegistry::default()
11+
}
1512

1613
#[fixture]
17-
#[expect(
18-
unused_braces,
19-
reason = "rustc false positive for single-line rstest fixtures"
20-
)]
21-
#[allow(unfulfilled_lint_expectations)]
2214
fn push_setup() -> (PushQueues<u8>, PushHandle<u8>) {
2315
PushQueues::<u8>::builder()
2416
.high_capacity(1)

tests/support.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ use wireframe::push::{PushQueues, PushQueuesBuilder};
44

55
/// Returns a builder with unit capacities for reuse across tests.
66
#[must_use]
7-
pub fn builder() -> PushQueuesBuilder<u8> {
8-
PushQueues::<u8>::builder().high_capacity(1).low_capacity(1)
7+
pub fn builder<F: Send + 'static>() -> PushQueuesBuilder<F> {
8+
PushQueues::<F>::builder().high_capacity(1).low_capacity(1)
99
}

0 commit comments

Comments
 (0)