My personal site cherry.computer
htmx tailwind axum askama

fix: pass query parameter to fetch scrobble if SSR timed out

cherry.computer f42751e3 0f0fe58c

verified
+15 -3
+2 -1
frontend/esbuild.js
··· 42 method: req.method, 43 headers: req.headers, 44 }; 45 const route = 46 - req.url === "/" || req.url === "/scrobbles" 47 ? { hostname: "127.0.0.1", port: 8080 } 48 : { hostname: host, port }; 49 const routedOptions = { ...options, ...route };
··· 42 method: req.method, 43 headers: req.headers, 44 }; 45 + const url = new URL(`http://localhost${req.url}`); 46 const route = 47 + url.pathname === "/" || url.pathname === "/scrobbles" 48 ? { hostname: "127.0.0.1", port: 8080 } 49 : { hostname: host, port }; 50 const routedOptions = { ...options, ...route };
+12 -1
server/src/main.rs
··· 10 use askama::Template; 11 use async_stream::stream; 12 use axum::{ 13 http::{HeaderName, HeaderValue, StatusCode}, 14 response::{sse, Html, IntoResponse, Sse}, 15 routing::{get, get_service}, 16 Extension, Router, 17 }; 18 use tokio::time::{self, MissedTickBehavior}; 19 use tokio_stream::Stream; 20 use tower::ServiceBuilder; ··· 60 }) 61 } 62 63 async fn get_scrobble( 64 Extension(mut monitor): Extension<ScrobbleMonitor>, 65 ) -> Sse<impl Stream<Item = Result<sse::Event, Infallible>>> { 66 let stream = stream! { 67 let mut interval = time::interval(Duration::from_secs(30)); 68 interval.set_missed_tick_behavior(MissedTickBehavior::Skip); 69 - interval.tick().await; 70 loop { 71 interval.tick().await; 72 let template = match monitor.get_scrobble().await {
··· 10 use askama::Template; 11 use async_stream::stream; 12 use axum::{ 13 + extract::Query, 14 http::{HeaderName, HeaderValue, StatusCode}, 15 response::{sse, Html, IntoResponse, Sse}, 16 routing::{get, get_service}, 17 Extension, Router, 18 }; 19 + use serde::Deserialize; 20 use tokio::time::{self, MissedTickBehavior}; 21 use tokio_stream::Stream; 22 use tower::ServiceBuilder; ··· 62 }) 63 } 64 65 + #[derive(Deserialize)] 66 + struct ScrobbleQuery { 67 + #[serde(default)] 68 + immediate: bool, 69 + } 70 + 71 async fn get_scrobble( 72 Extension(mut monitor): Extension<ScrobbleMonitor>, 73 + Query(ScrobbleQuery { immediate }): Query<ScrobbleQuery>, 74 ) -> Sse<impl Stream<Item = Result<sse::Event, Infallible>>> { 75 let stream = stream! { 76 let mut interval = time::interval(Duration::from_secs(30)); 77 interval.set_missed_tick_behavior(MissedTickBehavior::Skip); 78 + if !immediate { 79 + interval.tick().await; 80 + } 81 loop { 82 interval.tick().await; 83 let template = match monitor.get_scrobble().await {
+1 -1
server/templates/index.html
··· 89 <div 90 class="scrobble-bar" 91 hx-ext="sse" 92 - sse-connect="/scrobbles" 93 sse-swap="scrobble" 94 > 95 {%- match scrobble %} {%- when Some with (ScrobblesTemplate {intro, now_playing, image, srcset}) %}
··· 89 <div 90 class="scrobble-bar" 91 hx-ext="sse" 92 + sse-connect="/scrobbles{% if scrobble.is_none() %}?immediate=true{% endif %}" 93 sse-swap="scrobble" 94 > 95 {%- match scrobble %} {%- when Some with (ScrobblesTemplate {intro, now_playing, image, srcset}) %}