Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh Libraries on FileSystem Changes, Invalidate Cache after Indexing & Fix Continual Revalidation of Authorisation Tokens #154

Merged
merged 7 commits into from
Dec 21, 2024
20 changes: 10 additions & 10 deletions apps/web/app/(app)/search/SearchComponent.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
"use client";

import { useState, useEffect } from "react";
import Link from "next/link";
import HorizontalCard from "@/components/Music/Card/HorizontalCard";
import { useSearchParams } from "next/navigation";
import { searchLibrary, searchYouTube } from "@music/sdk";
import TopResultsCard from "@/components/Music/Card/Search/TopResultsCard";
import { searchLibrary, searchYouTube } from "@music/sdk";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { useEffect, useState } from "react";

import { DialogFooter, Dialog } from "@music/ui/components/dialog";
import { DialogTrigger, DialogContent } from "@radix-ui/react-dialog";
import ReactPlayer from "react-player";
import Image from "next/image";
import { YoutubeIcon } from "lucide-react";
import PageGradient from "@/components/Layout/PageGradient";
import { Dialog, DialogFooter } from "@music/ui/components/dialog";
import { DialogContent, DialogTrigger } from "@radix-ui/react-dialog";
import { YoutubeIcon } from "lucide-react";
import Image from "next/image";
import ReactPlayer from "react-player";

interface YouTubeVideo {
id: string;
Expand Down Expand Up @@ -120,7 +120,7 @@ export default function SearchComponent() {
<TopResultCardSkeleton />
</div>
) : (
results && results[0] && <><TopResultsCard result={results[0]} /> <PageGradient imageSrc={results[0].album_object.cover_url}/></>
results && results[0] && <><TopResultsCard result={results[0]} /> <PageGradient imageSrc={results[0]?.album_object?.cover_url ?? "/snf.png"} /></>
)}
</div>
</div>
Expand Down
9 changes: 4 additions & 5 deletions apps/web/components/Layout/SplashScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"use client";

import pl from "@/assets/pl-tp.png";
import { isValid } from "@music/sdk";
import { deleteCookie } from "cookies-next";
import { Loader2Icon } from "lucide-react";
import Image from "next/image";
import { useRouter } from "next/navigation";
import React, { useEffect, useState } from "react";
import { useSession } from "../Providers/AuthProvider";
import { isValid } from "@music/sdk";
import { deleteCookie } from "cookies-next";

interface SplashScreenProps {
children: React.ReactNode;
Expand All @@ -26,10 +26,9 @@ const SplashScreen: React.FC<SplashScreenProps> = ({ children }) => {
setLoading(true);

const validationResult = await isValid();

if (!validationResult.status) {
deleteCookie('plm_accessToken');
deleteCookie('plm_refreshToken');
deleteCookie('plm_accessToken');
push('/login');
return;
}
Expand Down Expand Up @@ -101,4 +100,4 @@ const SplashScreen: React.FC<SplashScreenProps> = ({ children }) => {
return <>{children}</>;
};

export default SplashScreen;
export default SplashScreen;
4 changes: 2 additions & 2 deletions apps/web/components/Music/Card/Search/TopResultsCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export default function TopResultsCard({ result }: ResultCardProps) {
}, [result.id, result.item_type]);

const coverUrl = result.item_type === "song"
? song?.album_object.cover_url
? song?.album_object?.cover_url
: result.item_type === "album"
? album?.cover_url
: result.item_type === "artist"
Expand Down Expand Up @@ -89,7 +89,7 @@ export default function TopResultsCard({ result }: ResultCardProps) {
if (!song) return;
setImageSrc(imageSrc);
setPlayerArtist({ id: song.artist_object.id, name: song.artist });
setPlayerAlbum({ id: song.album_object.id, name: song.album_object.name, cover_url: song.album_object.cover_url });
setPlayerAlbum({ id: song?.album_object?.id, name: song?.album_object?.name, cover_url: song?.album_object?.cover_url });
try {
const songInfo = await getSongInfo(song.id);
setPlayerSong(songInfo);
Expand Down
1 change: 1 addition & 0 deletions crates/backend/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ levenshtein = "1.0.5"
libsqlite3-sys = { version = "0.29.0", features = ["bundled"] }
lofty = "0.18.2"
mime_guess = "2.0.5"
notify = "7.0.0"
rand = "0.8.5"
ravif = "0.11.9"
rayon = "1.8.0"
Expand Down
64 changes: 58 additions & 6 deletions crates/backend/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ use actix_cors::Cors;
use actix_web::HttpResponse;
use actix_web::{middleware, web, App, HttpServer};
use actix_web_httpauth::middleware::HttpAuthentication;
use notify::{Event, RecursiveMode, Watcher};
use routes::authentication::{admin_guard, is_valid, refresh};
use tokio::sync::broadcast;
use tokio::task;
use tracing::{info, Level};
use tracing::{error, info, Level};
use tracing_subscriber::FmtSubscriber;

use routes::{album, database, genres, music};
Expand All @@ -21,7 +23,7 @@ use routes::authentication::{login, register, validator};
use routes::filesystem;
use routes::image::image;
use routes::music::{
index_library_no_cover_url, process_library,
index, index_library_no_cover_url, library_refresh, process_music_library_no_ws, read_library_paths, Libraries
};
use routes::playlist;
use routes::search::{self, populate_search_data};
Expand All @@ -31,7 +33,7 @@ use routes::song;
use routes::user;
use routes::web as web_routes;

use utils::config;
use utils::config::{self, get_libraries_config_path};
use utils::database::database::{migrations_ran, redo_migrations};
use utils::database::database::run_migrations;
// use utils::update::check_for_updates;
Expand Down Expand Up @@ -131,6 +133,56 @@ async fn main() -> std::io::Result<()> {

info!("Starting server on port {}", port);

let (tx, _rx) = broadcast::channel(16);
let tx_clone = tx.clone();

std::thread::spawn(move || {
let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
match res {
Ok(_) => {
if let Err(e) = tx_clone.send(()) {
error!("Failed to send watch event: {}", e);
}
}
Err(e) => error!("Watch error: {}", e),
}
}).expect("Failed to create watcher");

let config_content = std::fs::read_to_string(get_libraries_config_path())
.expect("Failed to read libraries config");
let libraries: Libraries = serde_json::from_str(&config_content)
.expect("Failed to parse libraries config");

for library_path in &libraries.paths {
let path = std::path::Path::new(library_path);
let watch_path = path.parent().unwrap_or(path);

watcher.watch(watch_path, RecursiveMode::NonRecursive)
.expect("Failed to watch library path");

std::thread::park();
watcher.watch(watch_path, RecursiveMode::NonRecursive)
.expect("Failed to watch libraries path");
}

std::thread::park();
});

let mut rx = tx.subscribe();
std::thread::spawn(move || {
let rt = tokio::runtime::Runtime::new().expect("Failed to create runtime");

while rt.block_on(rx.recv()).is_ok() {
info!("Libraries file changed");
let paths = rt.block_on(read_library_paths());
for path in paths {
if let Err(e) = rt.block_on(process_music_library_no_ws(&path)) {
error!("Failed to process library {}: {}", path, e);
}
}
}
});

task::spawn(async move {
if !migrations_ran() {
if let Err(e) = run_migrations() {
Expand All @@ -141,10 +193,9 @@ async fn main() -> std::io::Result<()> {
if let Err(e) = populate_search_data().await {
eprintln!("Failed to populate search data: {}", e);
}

// run_modules().await;
});

HttpServer::new(move || {
let authentication = HttpAuthentication::with_fn(validator);
let admin = HttpAuthentication::with_fn(admin_guard);
Expand All @@ -170,7 +221,8 @@ async fn main() -> std::io::Result<()> {
let library_routes = web::scope("/library")
.wrap(admin)
.service(index_library_no_cover_url)
.service(process_library);
.service(index)
.service(library_refresh);

App::new()
.wrap(
Expand Down
Loading
Loading