Added artifical chunked response slowdown

This commit is contained in:
Joshua Barretto 2025-04-29 19:32:02 +01:00
parent 6a3009df26
commit c7073c8fbe
3 changed files with 58 additions and 4 deletions

3
Cargo.lock generated
View file

@ -1,6 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
version = 4
[[package]]
name = "addr2line"
@ -223,6 +223,7 @@ dependencies = [
"chrono",
"clap",
"hashbrown",
"http-body",
"itertools 0.14.0",
"rand",
"rand_chacha",

View file

@ -10,6 +10,7 @@ axum-server = { version = "0.7.2", features = ["tls-rustls"] }
chrono = "0.4.40"
clap = { version = "4.5.37", features = ["derive"] }
hashbrown = "0.15.2"
http-body = "1.0.1"
itertools = "0.14.0"
rand = "0.9.1"
rand_chacha = "0.9.0"

View file

@ -1,21 +1,32 @@
mod generator;
use axum::{extract::Path, response::Html, routing::get, Router};
use axum::{
body::{Body, Bytes},
extract::Path,
response::{Html, IntoResponse, Response},
routing::get,
Router,
};
use axum_server::{bind_rustls, tls_rustls::RustlsConfig};
use clap::Parser;
use hashbrown::HashMap;
use http_body::Frame;
use itertools::Itertools;
use rand::{prelude::*, Rng as _};
use rand_chacha::{rand_core::SeedableRng, ChaCha8Rng};
use std::{
borrow::Cow,
convert::Infallible,
path::PathBuf,
pin::Pin,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
task::{Context, Poll},
time::Duration,
};
use tokio::time::{interval, Interval};
pub type Rng = ChaCha8Rng;
@ -43,6 +54,42 @@ fn create_rng(seed_bytes: impl IntoIterator<Item = u8>) -> Rng {
const COUNT_FILE: &str = "count.txt";
const SLOW_CHUNK_SIZE: usize = 50;
const SLOW_DURATION: Duration = Duration::from_millis(250);
struct SlowBody {
bytes: Bytes,
interval: Interval,
}
impl http_body::Body for SlowBody {
type Data = Bytes;
type Error = Infallible;
fn poll_frame(
mut self: Pin<&mut Self>,
cx: &mut Context<'_>,
) -> Poll<Option<Result<Frame<Self::Data>, Self::Error>>> {
match self.interval.poll_tick(cx) {
Poll::Ready(_) => {
if self.bytes.is_empty() {
Poll::Ready(None)
} else {
let split_len = self.bytes.len().min(SLOW_CHUNK_SIZE);
Poll::Ready(Some(Ok(Frame::data(self.bytes.split_to(split_len)))))
}
}
Poll::Pending => Poll::Pending,
}
}
}
impl IntoResponse for SlowBody {
fn into_response(self) -> Response {
Html(Body::new(self)).into_response()
}
}
#[tokio::main]
async fn main() {
let args = Args::parse();
@ -105,7 +152,7 @@ async fn main() {
content
});
Html(format!(
let html = format!(
"<!DOCTYPE html>
<html>
<head>
@ -119,7 +166,12 @@ async fn main() {
</body>
</html>"
))
);
SlowBody {
bytes: html.into(),
interval: interval(SLOW_DURATION),
}
}),
)
};