Server tools to backfill, tail, mirror, and verify PLC logs

nicer pages or whatever

+54 -10
+2 -2
Cargo.lock
··· 211 212 [[package]] 213 name = "brotli" 214 - version = "8.0.1" 215 source = "registry+https://github.com/rust-lang/crates.io-index" 216 - checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" 217 dependencies = [ 218 "alloc-no-stdlib", 219 "alloc-stdlib",
··· 211 212 [[package]] 213 name = "brotli" 214 + version = "8.0.2" 215 source = "registry+https://github.com/rust-lang/crates.io-index" 216 + checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" 217 dependencies = [ 218 "alloc-no-stdlib", 219 "alloc-stdlib",
+2 -2
src/bin/allegedly.rs
··· 234 235 let (tx, rx) = mpsc::channel(2); 236 // upstream poller 237 tokio::task::spawn(async move { 238 log::info!("starting poll reader..."); 239 - let mut url = args.upstream; 240 url.set_path("/export"); 241 tokio::task::spawn( 242 async move { poll_upstream(Some(latest), url, tx).await.unwrap() }, ··· 249 pages_to_pg(poll_db, rx).await.unwrap(); 250 }); 251 252 - serve(wrap, bind).await.unwrap(); 253 } 254 Commands::Tail { after } => { 255 let mut url = args.upstream;
··· 234 235 let (tx, rx) = mpsc::channel(2); 236 // upstream poller 237 + let mut url = args.upstream.clone(); 238 tokio::task::spawn(async move { 239 log::info!("starting poll reader..."); 240 url.set_path("/export"); 241 tokio::task::spawn( 242 async move { poll_upstream(Some(latest), url, tx).await.unwrap() }, ··· 249 pages_to_pg(poll_db, rx).await.unwrap(); 250 }); 251 252 + serve(&args.upstream, wrap, bind).await.unwrap(); 253 } 254 Commands::Tail { after } => { 255 let mut url = args.upstream;
+50 -6
src/mirror.rs
··· 14 struct State { 15 client: Client, 16 plc: Url, 17 } 18 19 #[handler] 20 - fn hello() -> String { 21 - logo("mirror") 22 } 23 24 #[handler] ··· 33 .await 34 .map_err(|e| { 35 log::error!("upstream req fail: {e}"); 36 - Error::from_string("request to plc server failed", StatusCode::BAD_GATEWAY) 37 })?; 38 let mut res = Response::default(); 39 upstream_res.headers().iter().for_each(|(k, v)| { ··· 51 Ok(()) 52 } 53 54 - pub async fn serve(plc: Url, bind: SocketAddr) -> std::io::Result<()> { 55 - let client = Client::builder() 56 .timeout(Duration::from_secs(3)) 57 .build() 58 .unwrap(); 59 - let state = State { client, plc }; 60 61 let app = Route::new() 62 .at("/", get(hello)) ··· 66 .with(Compression::new()) 67 .with(CatchPanic::new()) 68 .with(Tracing); 69 Server::new(TcpListener::bind(bind)).run(app).await 70 }
··· 14 struct State { 15 client: Client, 16 plc: Url, 17 + upstream: Url, 18 } 19 20 #[handler] 21 + fn hello(Data(State { upstream, .. }): Data<&State>) -> String { 22 + format!( 23 + r#"{} 24 + 25 + This is a PLC[1] mirror running Allegedly[2] in mirror mode. Allegedly synchronizes and proxies to a downstream PLC reference server instance[3] (why?[4]). 26 + 27 + 28 + Configured upstream: 29 + 30 + {upstream} 31 + 32 + 33 + Available APIs: 34 + 35 + - All PLC GET requests [5]. 36 + - Rejects POSTs. This is a mirror. 37 + 38 + try `GET /{{did}}` to resolve an identity 39 + 40 + 41 + [1] https://web.plc.directory 42 + [2] https://tangled.org/@microcosm.blue/Allegedly 43 + [3] https://github.com/did-method-plc/did-method-plc 44 + [4] https://updates.microcosm.blue/3lz7nwvh4zc2u 45 + [5] https://web.plc.directory/api/redoc 46 + 47 + "#, 48 + logo("mirror") 49 + ) 50 + } 51 + 52 + fn failed_to_reach_wrapped() -> String { 53 + format!( 54 + r#"{} 55 + 56 + Failed to reach the wrapped reference PLC server. Sorry. 57 + "#, 58 + logo("mirror 502 :( ") 59 + ) 60 } 61 62 #[handler] ··· 71 .await 72 .map_err(|e| { 73 log::error!("upstream req fail: {e}"); 74 + Error::from_string(failed_to_reach_wrapped(), StatusCode::BAD_GATEWAY) 75 })?; 76 let mut res = Response::default(); 77 upstream_res.headers().iter().for_each(|(k, v)| { ··· 89 Ok(()) 90 } 91 92 + pub async fn serve(upstream: &Url, plc: Url, bind: SocketAddr) -> std::io::Result<()> { 93 + let wrapped_req_client = Client::builder() 94 .timeout(Duration::from_secs(3)) 95 .build() 96 .unwrap(); 97 + 98 + let state = State { 99 + client: wrapped_req_client, 100 + plc, 101 + upstream: upstream.clone(), 102 + }; 103 104 let app = Route::new() 105 .at("/", get(hello)) ··· 109 .with(Compression::new()) 110 .with(CatchPanic::new()) 111 .with(Tracing); 112 + 113 Server::new(TcpListener::bind(bind)).run(app).await 114 }