➕ 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