A decentralized music tracking and discovery platform built on AT Protocol 🎵

[scrobbler] handle concurrent jellyfin scrobbles

+24 -4
+6 -3
crates/scrobbler/src/scrobbler.rs
··· 408 408 return Err(Error::msg("User not found")); 409 409 } 410 410 411 - let user = user.unwrap(); 411 + 412 + cache.setex( 413 + &format!("listenbrainz:emby:{}:{}:{}", artist, track, did), 414 + "1", 415 + 60 * 5, // 5 minutes 416 + )?; 412 417 413 418 let spofity_tokens = repo::spotify_token::get_spotify_tokens(pool, 100).await?; 414 419 ··· 432 437 duration: None, 433 438 ignored: None, 434 439 }; 435 - 436 - let did = user.did.clone(); 437 440 438 441 /* 439 442 0. check if scrobble is cached
+18 -1
crates/webscrobbler/src/handlers.rs
··· 2 2 use actix_web::{get, post, web, HttpRequest, HttpResponse, Responder}; 3 3 use owo_colors::OwoColorize; 4 4 use sqlx::{Pool, Postgres}; 5 - use crate::{cache::Cache, repo, scrobbler::scrobble, types::ScrobbleRequest, BANNER}; 5 + use crate::{cache::Cache, musicbrainz::artist, repo, scrobbler::scrobble, types::ScrobbleRequest, BANNER}; 6 6 use tokio_stream::StreamExt; 7 7 8 8 #[macro_export] ··· 73 73 74 74 75 75 let cache = cache.get_ref().clone(); 76 + 77 + if params.data.song.connector.id == "emby" { 78 + let artist = params.data.song.parsed.artist.clone(); 79 + let track = params.data.song.parsed.track.clone(); 80 + let cached = cache.get(&format!("listenbrainz:emby:{}:{}:{}", artist, track, user.did)); 81 + 82 + if cached.is_err() { 83 + println!("Failed to check cache for Emby scrobble: {}", cached.unwrap_err()); 84 + return Ok(HttpResponse::Ok().body("Failed to check cache for Emby scrobble")); 85 + } 86 + 87 + if cached.unwrap().is_some() { 88 + println!("Skipping duplicate scrobble for Emby: {} - {}", artist, track); 89 + return Ok(HttpResponse::Ok().body("Skipping duplicate scrobble for Emby")); 90 + } 91 + } 92 + 76 93 77 94 scrobble(&pool, &cache, params, &user.did).await 78 95 .map_err(|err| actix_web::error::ErrorInternalServerError(format!("Failed to scrobble: {}", err)))?;