Each published crate (irtt-rs, irtt-client, irtt-server, irtt-stats, irtt-proto) now points crates.io at its own README instead of inheriting the root project README via the workspace-wide readme default, which is removed. Each crate README is a short landing page: what the crate is, who should use it, which sibling crate to use instead if this isn't the right abstraction level, and links to docs.rs and the main repository. Add real Cargo example targets teaching irtt-client's blocking/Tokio/ managed API tiers, a basic and a multi-listener irtt-server example, and an irtt-stats example contrasting finite vs continuous retention. irtt-proto intentionally has none. Update each crate's top-level rustdoc to explain its API-tier choices and point at the examples, and enable docs.rs rustdoc example scraping for irtt-client and irtt-server (via doc-scrape-examples on each example target, needed because the crate has dev-dependencies). The client examples are caller-paced against next_send_deadline() rather than sending on every loop iteration, bound their receive wait by the next send/timeout deadline instead of awaiting indefinitely, poll timeouts on a short fixed cadence, and surface send/receive/close errors instead of discarding them via unwrap_or_default()/if-let-Ok -- so they demonstrate correct pacing and terminate/report cleanly rather than racing the server, hanging on a lost reply, or silently dropping a failed final close.
74 lines
2.5 KiB
Rust
74 lines
2.5 KiB
Rust
//! Managed multi-target client example (`tokio` feature).
|
|
//!
|
|
//! [`BlockingManagedClient`] runs one or more targets under a dedicated
|
|
//! current-thread Tokio runtime and exposes a synchronous handle, so a caller
|
|
//! that does not want to touch Tokio directly can still get managed
|
|
//! multi-target orchestration, retries, and a lossy event stream.
|
|
//!
|
|
//! Run a server first, then run this example:
|
|
//!
|
|
//! ```text
|
|
//! cargo run -p irtt-rs --bin irtt-server --features server
|
|
//! cargo run -p irtt-client --example managed_client --features tokio
|
|
//! ```
|
|
//!
|
|
//! This example does not wait for the managed run to finish naturally: it
|
|
//! requests a stop after a fixed short window so it exits promptly even
|
|
//! without a reachable server.
|
|
|
|
use std::time::Duration;
|
|
|
|
use irtt_client::managed::{
|
|
BlockingManagedClient, ManagedClientConfig, ManagedCompletionPolicy, ManagedEvent,
|
|
ManagedTargetConfig,
|
|
};
|
|
use irtt_client::ClientConfig;
|
|
|
|
fn main() {
|
|
let config = ManagedClientConfig {
|
|
client: ClientConfig {
|
|
duration: None,
|
|
interval: Duration::from_millis(200),
|
|
open_timeouts: vec![Duration::from_millis(300)],
|
|
..Default::default()
|
|
},
|
|
completion: ManagedCompletionPolicy::ExplicitStop,
|
|
..Default::default()
|
|
};
|
|
let targets = vec![ManagedTargetConfig::new("local", "127.0.0.1:2112")];
|
|
|
|
let (owner, mut events) = match BlockingManagedClient::start_with_subscription(config, targets)
|
|
{
|
|
Ok(started) => started,
|
|
Err(err) => {
|
|
eprintln!("failed to start managed client: {err}");
|
|
return;
|
|
}
|
|
};
|
|
|
|
let stop_after = Duration::from_secs(1);
|
|
let deadline = std::time::Instant::now() + stop_after;
|
|
while std::time::Instant::now() < deadline {
|
|
match events.try_recv() {
|
|
Ok(event) => print_event(&event),
|
|
Err(_) => std::thread::sleep(Duration::from_millis(50)),
|
|
}
|
|
}
|
|
|
|
// `stop()` requests the stop synchronously; the returned receipt is only
|
|
// useful for awaiting durable acknowledgement, which this blocking
|
|
// example does not need.
|
|
std::mem::drop(owner.handle().stop());
|
|
match owner.join() {
|
|
Ok(outcome) => println!("managed run ended: {:?}", outcome.end_reason),
|
|
Err(err) => eprintln!("managed worker did not join cleanly: {err}"),
|
|
}
|
|
}
|
|
|
|
fn print_event(event: &ManagedEvent) {
|
|
match event {
|
|
ManagedEvent::Client { target, event } => println!("{}: {event:?}", target.id),
|
|
other => println!("{other:?}"),
|
|
}
|
|
}
|