diff options
| author | metamuffin <metamuffin@disroot.org> | 2026-01-15 02:57:31 +0100 |
|---|---|---|
| committer | metamuffin <metamuffin@disroot.org> | 2026-01-15 02:57:31 +0100 |
| commit | c836b650eaf4ba33b1cfd2b475971b3ccc9f69b7 (patch) | |
| tree | 2ea722aff33252ff2e3662faee63cabb223339c3 /import/src | |
| parent | 8c0ee6d17fe0dbd7748e7b60ff01a0e8f25faa51 (diff) | |
| download | jellything-c836b650eaf4ba33b1cfd2b475971b3ccc9f69b7.tar jellything-c836b650eaf4ba33b1cfd2b475971b3ccc9f69b7.tar.bz2 jellything-c836b650eaf4ba33b1cfd2b475971b3ccc9f69b7.tar.zst | |
new update_node_init
Diffstat (limited to 'import/src')
| -rw-r--r-- | import/src/lib.rs | 75 | ||||
| -rw-r--r-- | import/src/plugins/acoustid.rs | 4 | ||||
| -rw-r--r-- | import/src/plugins/infojson.rs | 8 | ||||
| -rw-r--r-- | import/src/plugins/media_info.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/misc.rs | 15 | ||||
| -rw-r--r-- | import/src/plugins/mod.rs | 19 | ||||
| -rw-r--r-- | import/src/plugins/tags.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/tmdb.rs | 4 | ||||
| -rw-r--r-- | import/src/plugins/trakt.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/vgmdb.rs | 1 | ||||
| -rw-r--r-- | import/src/plugins/wikimedia_commons.rs | 4 |
11 files changed, 85 insertions, 48 deletions
diff --git a/import/src/lib.rs b/import/src/lib.rs index aab0c70..ad929fa 100644 --- a/import/src/lib.rs +++ b/import/src/lib.rs @@ -14,8 +14,12 @@ use crate::{ }; use anyhow::{Context, Result, anyhow}; use jellycache::{HashKey, cache_memory, cache_store}; -use jellycommon::{NodeID, Visibility}; -use jellydb::Database; +use jellycommon::jellyobject::{self, Object, ObjectBuffer, Tag, TypedTag}; +use jellydb::{ + backends::Database, + query::{Filter, Query, Sort}, + table::{RowNum, Table}, +}; use jellyremuxer::{ demuxers::create_demuxer_autodetect, matroska::{self, AttachedFile, Segment}, @@ -29,6 +33,7 @@ use serde::{Deserialize, Serialize}; use std::{ collections::HashSet, fs::{File, read_to_string}, + marker::PhantomData, mem::swap, path::{Path, PathBuf}, sync::{Arc, LazyLock, Mutex}, @@ -76,7 +81,49 @@ pub fn is_importing() -> bool { IMPORT_SEM.available_permits() == 0 } -pub async fn import_wrap(db: Database, incremental: bool) -> Result<()> { +pub struct NodeID(pub String); + +const NODE_ID: TypedTag<&str> = TypedTag(Tag(0x8123), PhantomData); + +struct DatabaseTables { + db: Arc<dyn Database>, + nodes: Table, +} + +fn node_id_query(node: &NodeID) -> Query { + Query { + filter: Filter::Match( + jellyobject::Path(vec![NODE_ID.0]), + node.0.as_bytes().to_vec(), + ), + sort: Sort::None, + } +} + +impl DatabaseTables { + pub fn update_node_init( + &self, + node: NodeID, + mut update: impl FnMut(Object) -> Option<ObjectBuffer>, + ) -> Result<()> { + self.db.write_transaction(&mut |txn| { + let node = match self.nodes.query_single(txn, node_id_query(&node)) { + Some(r) => r, + None => self + .nodes + .insert(txn, ObjectBuffer::new(&mut [(NODE_ID.0, &node.0.as_str())]))?, + }; + let ob = self.nodes.get(txn, node)?.unwrap(); + if let Some(changed) = update(ob.as_object()) { + self.nodes.update(txn, node, changed)?; + } + Ok(()) + })?; + Ok(()) + } +} + +pub async fn import_wrap(db: DatabaseTables, incremental: bool) -> Result<()> { let _sem = IMPORT_SEM.try_acquire().context("already importing")?; let rt = Handle::current(); @@ -86,9 +133,9 @@ pub async fn import_wrap(db: Database, incremental: bool) -> Result<()> { .build()?; let jh = spawn_blocking(move || { - tp.install(|| { + tp.install(move || { reporting::start_import(); - reporting::catch(import(&db, &rt, incremental)); + reporting::catch(import(db, &rt, incremental)); reporting::end_import(); }) }); @@ -98,7 +145,7 @@ pub async fn import_wrap(db: Database, incremental: bool) -> Result<()> { Ok(()) } -fn import(db: &Database, rt: &Handle, incremental: bool) -> Result<()> { +fn import(db: DatabaseTables, rt: &Handle, incremental: bool) -> Result<()> { let plugins = init_plugins(&CONF.api); let files = Mutex::new(Vec::new()); import_traverse( @@ -165,11 +212,11 @@ impl Default for InheritedFlags { fn import_traverse( path: &Path, - db: &Database, + db: DatabaseTables, incremental: bool, - parent: NodeID, + parent: Option<RowNum>, mut iflags: InheritedFlags, - out: &Mutex<Vec<(PathBuf, NodeID, InheritedFlags)>>, + out: &Mutex<Vec<(PathBuf, RowNum, InheritedFlags)>>, ) -> Result<()> { if path.is_dir() { reporting::set_task(format!("indexing {path:?}")); @@ -244,7 +291,7 @@ fn import_file( db, rt, iflags, - nodes, + pending_nodes: nodes, }; let filename = path.file_name().unwrap().to_string_lossy(); if filename == "flags" { @@ -343,7 +390,7 @@ fn import_file( } fn process_node( - db: &Database, + dba: DatabaseTables, rt: &Handle, plugins: &[Box<dyn ImportPlugin>], nodes: &Mutex<HashSet<NodeID>>, @@ -369,10 +416,10 @@ fn process_node( reporting::catch( p.process( &ImportContext { - db, + dba, rt, iflags: InheritedFlags::default(), - nodes, + pending_nodes: nodes, }, node, &data, @@ -383,7 +430,7 @@ fn process_node( } } -fn update_mtime(db: &Database, path: &Path) -> Result<()> { +fn update_mtime(db: DatabaseTables, path: &Path) -> Result<()> { let meta = path.metadata()?; let mtime = meta.modified()?.duration_since(UNIX_EPOCH)?.as_secs(); db.set_import_file_mtime(path, mtime)?; diff --git a/import/src/plugins/acoustid.rs b/import/src/plugins/acoustid.rs index 55c2123..b93533a 100644 --- a/import/src/plugins/acoustid.rs +++ b/import/src/plugins/acoustid.rs @@ -9,7 +9,7 @@ use crate::{ }; use anyhow::{Context, Result}; use jellycache::{HashKey, cache_memory}; -use jellycommon::{IdentifierType, NodeID}; +use jellydb::table::RowNum; use jellyremuxer::matroska::Segment; use log::info; use reqwest::{ @@ -166,7 +166,7 @@ impl ImportPlugin for AcoustID { ..Default::default() } } - fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, _seg: &Segment) -> Result<()> { + fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> { if !ct.iflags.use_acoustid { return Ok(()); } diff --git a/import/src/plugins/infojson.rs b/import/src/plugins/infojson.rs index 3aac3ec..fd15e03 100644 --- a/import/src/plugins/infojson.rs +++ b/import/src/plugins/infojson.rs @@ -4,11 +4,9 @@ Copyright (C) 2026 metamuffin <metamuffin.org> */ use anyhow::{Context, Result, anyhow}; +use chrono::{Utc, format::Parsed}; use jellycache::cache_read; -use jellycommon::{ - IdentifierType, NodeID, NodeKind, RatingType, - chrono::{Utc, format::Parsed}, -}; +use jellydb::table::RowNum; use jellyremuxer::matroska::{AttachedFile, Segment}; use log::info; use serde::{Deserialize, Serialize}; @@ -168,7 +166,7 @@ impl ImportPlugin for Infojson { ..Default::default() } } - fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> { + fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> { let filename = path.file_name().unwrap().to_string_lossy(); if filename != "channel.info.json" { return Ok(()); diff --git a/import/src/plugins/media_info.rs b/import/src/plugins/media_info.rs index d2aa5af..da445a3 100644 --- a/import/src/plugins/media_info.rs +++ b/import/src/plugins/media_info.rs @@ -6,7 +6,6 @@ use crate::plugins::{ImportContext, ImportPlugin, PluginInfo}; use anyhow::{Result, anyhow}; -use jellycommon::{Chapter, NodeID, SourceTrack, SourceTrackKind, TrackSource}; use jellyremuxer::matroska::Segment; use std::path::Path; diff --git a/import/src/plugins/misc.rs b/import/src/plugins/misc.rs index 8a95b97..43bd118 100644 --- a/import/src/plugins/misc.rs +++ b/import/src/plugins/misc.rs @@ -6,7 +6,8 @@ use crate::plugins::{ImportContext, ImportPlugin, PluginInfo}; use anyhow::{Context, Result, bail}; use jellycache::{HashKey, cache_store}; -use jellycommon::{Asset, NodeID, NodeKind, PictureSlot, Visibility}; +use jellycommon::{PICT_BACKDROP, PICT_COVER}; +use jellydb::table::RowNum; use jellyremuxer::matroska::{AttachedFile, Segment}; use log::info; use regex::Regex; @@ -26,14 +27,14 @@ impl ImportPlugin for ImageFiles { ..Default::default() } } - fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> { + fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> { let filename = path.file_name().unwrap().to_string_lossy(); let slot = match filename.as_ref() { - "poster.jpeg" | "poster.webp" | "poster.png" => PictureSlot::Cover, - "backdrop.jpeg" | "backdrop.webp" | "backdrop.png" => PictureSlot::Backdrop, + "poster.jpeg" | "poster.webp" | "poster.png" => PICT_COVER, + "backdrop.jpeg" | "backdrop.webp" | "backdrop.png" => PICT_BACKDROP, _ => return Ok(()), }; - info!("import {slot} at {path:?}"); + info!("import {} at {path:?}", slot); let asset = Asset(cache_store( format!("media/literal/{}-{slot}.image", HashKey(path)), || { @@ -141,7 +142,7 @@ impl ImportPlugin for Children { ..Default::default() } } - fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> { + fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> { let filename = path.file_name().unwrap().to_string_lossy(); if filename.as_ref() == "children" { info!("import children at {path:?}"); @@ -172,7 +173,7 @@ impl ImportPlugin for EpisodeIndex { ..Default::default() } } - fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, _seg: &Segment) -> Result<()> { + fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, _seg: &Segment) -> Result<()> { let filename = path.file_name().unwrap().to_string_lossy(); if let Some(cap) = RE_EPISODE_FILENAME.captures(&filename) { if let Some(episode) = cap.name("episode").map(|m| m.as_str()) { diff --git a/import/src/plugins/mod.rs b/import/src/plugins/mod.rs index 3aeefdf..095fd39 100644 --- a/import/src/plugins/mod.rs +++ b/import/src/plugins/mod.rs @@ -15,19 +15,20 @@ pub mod vgmdb; pub mod wikidata; pub mod wikimedia_commons; -use crate::{ApiSecrets, InheritedFlags}; +use crate::{ApiSecrets, DatabaseTables, InheritedFlags}; use anyhow::Result; -use jellycommon::{Node, NodeID}; -use jellydb::Database; +use jellycommon::jellyobject::Object; +use jellydb::table::{RowNum, Table}; use jellyremuxer::matroska::Segment; use std::{collections::HashSet, path::Path, sync::Mutex}; use tokio::runtime::Handle; pub struct ImportContext<'a> { - pub db: &'a Database, + pub dba: DatabaseTables, + pub nodes: &'a Table, pub rt: &'a Handle, pub iflags: InheritedFlags, - pub nodes: &'a Mutex<HashSet<NodeID>>, + pub pending_nodes: &'a Mutex<HashSet<RowNum>>, } #[derive(Default, Clone, Copy)] @@ -41,19 +42,19 @@ pub struct PluginInfo { pub trait ImportPlugin: Send + Sync { fn info(&self) -> PluginInfo; - fn file(&self, ct: &ImportContext, parent: NodeID, path: &Path) -> Result<()> { + fn file(&self, ct: &ImportContext, parent: RowNum, path: &Path) -> Result<()> { let _ = (ct, parent, path); Ok(()) } - fn media(&self, ct: &ImportContext, node: NodeID, path: &Path, seg: &Segment) -> Result<()> { + fn media(&self, ct: &ImportContext, node: RowNum, path: &Path, seg: &Segment) -> Result<()> { let _ = (ct, node, path, seg); Ok(()) } - fn instruction(&self, ct: &ImportContext, node: NodeID, line: &str) -> Result<()> { + fn instruction(&self, ct: &ImportContext, node: RowNum, line: &str) -> Result<()> { let _ = (ct, node, line); Ok(()) } - fn process(&self, ct: &ImportContext, node: NodeID, data: &Node) -> Result<()> { + fn process(&self, ct: &ImportContext, node: RowNum, data: Object<'_>) -> Result<()> { let _ = (ct, node, data); Ok(()) } diff --git a/import/src/plugins/tags.rs b/import/src/plugins/tags.rs index 9fa5ea9..07e40cc 100644 --- a/import/src/plugins/tags.rs +++ b/import/src/plugins/tags.rs @@ -6,7 +6,6 @@ use crate::plugins::{ImportContext, ImportPlugin, PluginInfo}; use anyhow::Result; -use jellycommon::{IdentifierType, NodeID, NodeKind}; use jellyremuxer::matroska::Segment; use std::{collections::HashMap, path::Path}; diff --git a/import/src/plugins/tmdb.rs b/import/src/plugins/tmdb.rs index 5527b8b..ce9ae59 100644 --- a/import/src/plugins/tmdb.rs +++ b/import/src/plugins/tmdb.rs @@ -9,10 +9,6 @@ use crate::{ }; use anyhow::{Context, Result, anyhow, bail}; use jellycache::{EscapeKey, HashKey, cache_memory, cache_store}; -use jellycommon::{ - Asset, IdentifierType, Node, NodeID, PictureSlot, RatingType, - chrono::{Utc, format::Parsed}, -}; use log::info; use reqwest::{ Client, ClientBuilder, diff --git a/import/src/plugins/trakt.rs b/import/src/plugins/trakt.rs index c8ff52a..7981713 100644 --- a/import/src/plugins/trakt.rs +++ b/import/src/plugins/trakt.rs @@ -9,7 +9,6 @@ use crate::{ }; use anyhow::{Context, Result, anyhow, bail}; use jellycache::{HashKey, cache_memory}; -use jellycommon::{Appearance, CreditCategory, IdentifierType, Node, NodeID, NodeKind, RatingType}; use log::info; use reqwest::{ Client, ClientBuilder, diff --git a/import/src/plugins/vgmdb.rs b/import/src/plugins/vgmdb.rs index 83f677d..734c7af 100644 --- a/import/src/plugins/vgmdb.rs +++ b/import/src/plugins/vgmdb.rs @@ -10,7 +10,6 @@ use crate::{ }; use anyhow::{Context, Result}; use jellycache::{HashKey, cache, cache_store}; -use jellycommon::Asset; use log::info; use regex::Regex; use reqwest::{ diff --git a/import/src/plugins/wikimedia_commons.rs b/import/src/plugins/wikimedia_commons.rs index 58a28ae..c849b61 100644 --- a/import/src/plugins/wikimedia_commons.rs +++ b/import/src/plugins/wikimedia_commons.rs @@ -10,7 +10,6 @@ use crate::{ }; use anyhow::{Context, Result}; use jellycache::{EscapeKey, cache_store}; -use jellycommon::Asset; use reqwest::{ Client, ClientBuilder, header::{HeaderMap, HeaderName, HeaderValue}, @@ -40,7 +39,7 @@ impl WikimediaCommons { Self { client } } - pub fn image_by_filename(&self, filename: String, rt: &Handle) -> Result<Asset> { + pub fn image_by_filename(&self, filename: String, rt: &Handle) -> Result<String> { cache_store( format!("ext/wikimedia-commons/image/{}.image", EscapeKey(&filename)), move || { @@ -61,7 +60,6 @@ impl WikimediaCommons { }, ) .context("mediawiki image by filename") - .map(Asset) } } |