➕ update: add prototype for `tail -f` based on polling
parent
e79925dc14
commit
137e8e1bf8
|
@ -1720,6 +1720,17 @@ dependencies = [
|
||||||
"uom",
|
"uom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ptth_tail"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"reqwest",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"tracing-subscriber",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulldown-cmark"
|
name = "pulldown-cmark"
|
||||||
version = "0.8.0"
|
version = "0.8.0"
|
||||||
|
|
|
@ -23,4 +23,7 @@ ptth_server = { path = "crates/ptth_server" }
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
|
|
||||||
members = ["crates/*"]
|
members = [
|
||||||
|
"crates/*",
|
||||||
|
"tools/*",
|
||||||
|
]
|
||||||
|
|
|
@ -270,9 +270,7 @@ pub async fn run_server (
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
Ok (r) => {
|
Ok (x) => x,
|
||||||
r
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if req_resp.status () == StatusCode::NO_CONTENT {
|
if req_resp.status () == StatusCode::NO_CONTENT {
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
[package]
|
||||||
|
|
||||||
|
name = "ptth_tail"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Trish"]
|
||||||
|
edition = "2018"
|
||||||
|
license = "AGPL-3.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
|
||||||
|
anyhow = "1.0.34"
|
||||||
|
tracing = "0.1.21"
|
||||||
|
tracing-subscriber = "0.2.15"
|
||||||
|
|
||||||
|
[dependencies.reqwest]
|
||||||
|
version = "0.10.8"
|
||||||
|
features = ["stream"]
|
||||||
|
|
||||||
|
[dependencies.tokio]
|
||||||
|
version = "0.2.22"
|
||||||
|
features = ["full"]
|
|
@ -0,0 +1,80 @@
|
||||||
|
use std::{
|
||||||
|
convert::TryFrom,
|
||||||
|
io::{
|
||||||
|
self,
|
||||||
|
Write,
|
||||||
|
},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use reqwest::{
|
||||||
|
Client,
|
||||||
|
StatusCode,
|
||||||
|
};
|
||||||
|
use tokio::{
|
||||||
|
stream::StreamExt,
|
||||||
|
time::interval,
|
||||||
|
};
|
||||||
|
use tracing::{
|
||||||
|
debug, warn
|
||||||
|
};
|
||||||
|
use tracing_subscriber::{
|
||||||
|
EnvFilter,
|
||||||
|
fmt,
|
||||||
|
fmt::format::FmtSpan,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main () -> Result <(), anyhow::Error> {
|
||||||
|
fmt ()
|
||||||
|
.with_env_filter (EnvFilter::from_default_env ())
|
||||||
|
.with_span_events (FmtSpan::CLOSE)
|
||||||
|
.init ()
|
||||||
|
;
|
||||||
|
|
||||||
|
let client = Client::default ();
|
||||||
|
|
||||||
|
let server = "http://127.0.0.1:4000/files/log.txt";
|
||||||
|
|
||||||
|
let mut total_bytes_received = 0_u64;
|
||||||
|
let mut timer = interval (Duration::from_secs (2));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
timer.tick ().await;
|
||||||
|
|
||||||
|
let resp = match client
|
||||||
|
.get (server)
|
||||||
|
.header ("range", format! ("bytes={}-", total_bytes_received))
|
||||||
|
.send ().await {
|
||||||
|
Err (e) => {
|
||||||
|
warn! ("Reqwest send error: {:?}", e);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Ok (x) => x,
|
||||||
|
};
|
||||||
|
|
||||||
|
let status = resp.status ();
|
||||||
|
|
||||||
|
match status {
|
||||||
|
StatusCode::RANGE_NOT_SATISFIABLE => continue,
|
||||||
|
StatusCode::PARTIAL_CONTENT => (),
|
||||||
|
sc => {
|
||||||
|
debug! ("status code: {}", sc);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stream = resp.bytes_stream ();
|
||||||
|
|
||||||
|
while let Some (chunk) = stream.next ().await {
|
||||||
|
let chunk = match chunk {
|
||||||
|
Ok (x) => x,
|
||||||
|
Err (_) => break,
|
||||||
|
};
|
||||||
|
io::stdout ().write_all (&chunk)?;
|
||||||
|
total_bytes_received += u64::try_from (chunk.len ())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok (())
|
||||||
|
}
|
Loading…
Reference in New Issue