diff --git a/Cargo.lock b/Cargo.lock index 9a33888..675791e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -530,6 +530,54 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" +dependencies = [ + "cfg-if", + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "memoffset", + "scopeguard", +] + [[package]] name = "crossbeam-queue" version = "0.3.8" @@ -1399,6 +1447,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +[[package]] +name = "memoffset" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -1857,6 +1914,7 @@ dependencies = [ "axum", "clap 4.3.21", "comrak", + "crossbeam", "file-format", "frontmatter", "futures", diff --git a/Cargo.toml b/Cargo.toml index 99565e2..a56daf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,4 +26,5 @@ frontmatter = "0.4.0" file-format = "0.18.0" rss = "2.0.6" time = { version = "0.3.28", features = ["parsing", "formatting", "macros"] } -async-trait = "0.1.73" \ No newline at end of file +async-trait = "0.1.73" +crossbeam = "0.8.2" \ No newline at end of file diff --git a/flake.lock b/flake.lock index 2755e26..cb59d5a 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "advisory-db": { "flake": false, "locked": { - "lastModified": 1689698236, - "narHash": "sha256-Qz9JxGKeA3jwuj1CdK9ejMJ7VsJRdiZniF8lx4mft9s=", + "lastModified": 1696104803, + "narHash": "sha256-xdPl4PHzWaisHy4hQexpHJlx/3xAkCZrOFtEv3ygXco=", "owner": "rustsec", "repo": "advisory-db", - "rev": "4aa517564d1d06f0e79784c8ad973a59d68aa9c8", + "rev": "46754ce9372c13a7e9a05cf7d812fadfdca9cf57", "type": "github" }, "original": { @@ -26,11 +26,11 @@ "rust-overlay": "rust-overlay" }, "locked": { - "lastModified": 1688772518, - "narHash": "sha256-ol7gZxwvgLnxNSZwFTDJJ49xVY5teaSvF7lzlo3YQfM=", + "lastModified": 1696124486, + "narHash": "sha256-a/xfX9CZnNQoW38w7+fpxBJ8aFQVQQg+Va3OcHBBCZs=", "owner": "ipetkov", "repo": "crane", - "rev": "8b08e96c9af8c6e3a2b69af5a7fa168750fcf88e", + "rev": "af842d7319f8c3d9e5215a79306824897fcb667c", "type": "github" }, "original": { @@ -47,11 +47,11 @@ "rust-analyzer-src": [] }, "locked": { - "lastModified": 1689834114, - "narHash": "sha256-btRpL43gvbP+5+gHjaaeZ9Uv6x8LkjaO1kyvEN5rQTE=", + "lastModified": 1696141234, + "narHash": "sha256-0dZpggYjjmWEk+rGixiBHOHuQfLzEzNfrtjSig04s6Q=", "owner": "nix-community", "repo": "fenix", - "rev": "d55d856bcc50ae831f9355465f6a651034f6c8d4", + "rev": "9ccae1754eec0341b640d5705302ac0923d22875", "type": "github" }, "original": { @@ -81,11 +81,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1687709756, - "narHash": "sha256-Y5wKlQSkgEK2weWdOu4J3riRd+kV/VCgHsqLNTTWQ/0=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "dbabf0ca0c0c4bce6ea5eaf65af5cb694d2082c7", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -99,11 +99,11 @@ "systems": "systems_2" }, "locked": { - "lastModified": 1689068808, - "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "lastModified": 1694529238, + "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=", "owner": "numtide", "repo": "flake-utils", - "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "rev": "ff7b65b44d01cf9ba6a71320833626af21126384", "type": "github" }, "original": { @@ -114,11 +114,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1689752456, - "narHash": "sha256-VOChdECcEI8ixz8QY+YC4JaNEFwQd1V8bA0G4B28Ki0=", + "lastModified": 1696009558, + "narHash": "sha256-/1nNL8lCF0gn38XaFyu2ufpWcBFwCDZyYUxdZkM6GxU=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "7f256d7da238cb627ef189d56ed590739f42f13b", + "rev": "c182df2e68bd97deb32c7e4765adfbbbcaf75b60", "type": "github" }, "original": { @@ -149,11 +149,11 @@ ] }, "locked": { - "lastModified": 1688351637, - "narHash": "sha256-CLTufJ29VxNOIZ8UTg0lepsn3X03AmopmaLTTeHDCL4=", + "lastModified": 1695003086, + "narHash": "sha256-d1/ZKuBRpxifmUf7FaedCqhy0lyVbqj44Oc2s+P5bdA=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "f9b92316727af9e6c7fee4a761242f7f46880329", + "rev": "b87a14abea512d956f0b89d0d8a1e9b41f3e20ff", "type": "github" }, "original": { diff --git a/src/main.rs b/src/main.rs index 8438541..e9fc90b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,19 +16,20 @@ use axum::{ Router, }; use clap::Parser; +use crossbeam::channel::{unbounded, Receiver, Sender}; use file_format::{FileFormat, Kind}; use hyper::body::Bytes; use maud::{html, Markup, PreEscaped, Render, DOCTYPE}; use rss::ChannelBuilder; use serde::Deserialize; use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode, SqlitePoolOptions}; -use std::env; +use std::net::UdpSocket; use std::str::FromStr; +use std::{env, io, thread}; use time::{self, format_description, format_description::well_known::Rfc2822}; use tower_http::services::ServeDir; -use crate::cache::{Cache, init_cache}; - +use crate::cache::{init_cache, Cache}; #[derive(Parser)] struct Cli { @@ -104,25 +105,63 @@ async fn main() -> Result<(), sqlx::Error> { .layer(middleware::from_fn_with_state(state.clone(), cached_page)) .with_state(state); + // Create channels for sending messages and receiving results + let (to_gossip, from_gossip) = unbounded::(); + let (to_main, from_main) = unbounded(); + + // Spawn a worker thread + let gossip_server = thread::spawn(move || { + let _ = gossiper(from_main, to_gossip); + }); + println!("Running webserver on {}", args.bind); - axum::Server::bind(&args.bind.parse().unwrap()) - .serve(app.into_make_service()) - .await - .unwrap(); + let webserver = axum::Server::bind(&args.bind.parse().unwrap()).serve(app.into_make_service()); + tokio::spawn(webserver); + + loop { + for msg in from_gossip.try_iter() { + println!("{}", msg); + } + } + + // Optionally, wait for the worker thread to finish + gossip_server.join().unwrap(); Ok(()) } +fn gossiper(rx: Receiver, tx: Sender) -> io::Result<()> { + let mut buf = [0; 1024]; + let socket = UdpSocket::bind("0.0.0.0:1337")?; + let _ = tx.send("rdy".to_owned()); + + // Handle messages that are passed to us from the main thread. + for message in rx.try_iter() { + println!("Received: {}", message); + } + // Read from the UDP socket. + loop { + let (size, source) = socket.recv_from(&mut buf).expect("Failed to receive data"); + let request = String::from_utf8_lossy(&buf[..size]); + let _ = tx.send(request.to_string()).unwrap(); + + let response = "ack!"; + socket + .send_to(response.as_bytes(), source) + .expect("Failed to send response"); + } +} + async fn raw_blog_post(Path(post): Path) -> Result { let post = posts::blog_post(post); if post.is_err() { return Err(StatusCode::NOT_FOUND); } Ok(Response::builder() - .header("content-type", "text/plain") - .status(StatusCode::OK) - .body(Full::from(post.unwrap().content)) - .unwrap()) + .header("content-type", "text/plain") + .status(StatusCode::OK) + .body(Full::from(post.unwrap().content)) + .unwrap()) } async fn render_blog_post(Path(post): Path) -> Result {