➕ update: add prototype for `tail -f` based on polling
							parent
							
								
									e79925dc14
								
							
						
					
					
						commit
						137e8e1bf8
					
				| 
						 | 
				
			
			@ -1720,6 +1720,17 @@ dependencies = [
 | 
			
		|||
 "uom",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "ptth_tail"
 | 
			
		||||
version = "0.1.0"
 | 
			
		||||
dependencies = [
 | 
			
		||||
 "anyhow",
 | 
			
		||||
 "reqwest",
 | 
			
		||||
 "tokio",
 | 
			
		||||
 "tracing",
 | 
			
		||||
 "tracing-subscriber",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
[[package]]
 | 
			
		||||
name = "pulldown-cmark"
 | 
			
		||||
version = "0.8.0"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,4 +23,7 @@ ptth_server = { path = "crates/ptth_server" }
 | 
			
		|||
 | 
			
		||||
[workspace]
 | 
			
		||||
 | 
			
		||||
members = ["crates/*"]
 | 
			
		||||
members = [
 | 
			
		||||
	"crates/*",
 | 
			
		||||
	"tools/*",
 | 
			
		||||
]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -270,9 +270,7 @@ pub async fn run_server (
 | 
			
		|||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			},
 | 
			
		||||
			Ok (r) => {
 | 
			
		||||
				r
 | 
			
		||||
			},
 | 
			
		||||
			Ok (x) => x,
 | 
			
		||||
		};
 | 
			
		||||
		
 | 
			
		||||
		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