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

nicer pages or whatever

+54 -10
+2 -2
Cargo.lock
··· 211 211 212 212 [[package]] 213 213 name = "brotli" 214 - version = "8.0.1" 214 + version = "8.0.2" 215 215 source = "registry+https://github.com/rust-lang/crates.io-index" 216 - checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" 216 + checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" 217 217 dependencies = [ 218 218 "alloc-no-stdlib", 219 219 "alloc-stdlib",
+2 -2
src/bin/allegedly.rs
··· 234 234 235 235 let (tx, rx) = mpsc::channel(2); 236 236 // upstream poller 237 + let mut url = args.upstream.clone(); 237 238 tokio::task::spawn(async move { 238 239 log::info!("starting poll reader..."); 239 - let mut url = args.upstream; 240 240 url.set_path("/export"); 241 241 tokio::task::spawn( 242 242 async move { poll_upstream(Some(latest), url, tx).await.unwrap() }, ··· 249 249 pages_to_pg(poll_db, rx).await.unwrap(); 250 250 }); 251 251 252 - serve(wrap, bind).await.unwrap(); 252 + serve(&args.upstream, wrap, bind).await.unwrap(); 253 253 } 254 254 Commands::Tail { after } => { 255 255 let mut url = args.upstream;
+50 -6
src/mirror.rs
··· 14 14 struct State { 15 15 client: Client, 16 16 plc: Url, 17 + upstream: Url, 17 18 } 18 19 19 20 #[handler] 20 - fn hello() -> String { 21 - logo("mirror") 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 + ) 22 60 } 23 61 24 62 #[handler] ··· 33 71 .await 34 72 .map_err(|e| { 35 73 log::error!("upstream req fail: {e}"); 36 - Error::from_string("request to plc server failed", StatusCode::BAD_GATEWAY) 74 + Error::from_string(failed_to_reach_wrapped(), StatusCode::BAD_GATEWAY) 37 75 })?; 38 76 let mut res = Response::default(); 39 77 upstream_res.headers().iter().for_each(|(k, v)| { ··· 51 89 Ok(()) 52 90 } 53 91 54 - pub async fn serve(plc: Url, bind: SocketAddr) -> std::io::Result<()> { 55 - let client = Client::builder() 92 + pub async fn serve(upstream: &Url, plc: Url, bind: SocketAddr) -> std::io::Result<()> { 93 + let wrapped_req_client = Client::builder() 56 94 .timeout(Duration::from_secs(3)) 57 95 .build() 58 96 .unwrap(); 59 - let state = State { client, plc }; 97 + 98 + let state = State { 99 + client: wrapped_req_client, 100 + plc, 101 + upstream: upstream.clone(), 102 + }; 60 103 61 104 let app = Route::new() 62 105 .at("/", get(hello)) ··· 66 109 .with(Compression::new()) 67 110 .with(CatchPanic::new()) 68 111 .with(Tracing); 112 + 69 113 Server::new(TcpListener::bind(bind)).run(app).await 70 114 }