various: simplify code; work on security and performance

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I9a5114addcab5fbff430ab2b919b83466a6a6964
This commit is contained in:
raf 2026-02-02 17:32:11 +03:00
commit c4adc4e3e0
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF
75 changed files with 12921 additions and 358 deletions

View file

@ -161,17 +161,29 @@ async fn main() -> Result<()> {
let addr = format!("{}:{}", config.server.host, config.server.port);
// Initialize transcode service early so the job queue can reference it
let transcode_service: Option<Arc<pinakes_core::transcode::TranscodeService>> =
if config.transcoding.enabled {
Some(Arc::new(pinakes_core::transcode::TranscodeService::new(
config.transcoding.clone(),
)))
} else {
None
};
// Initialize job queue with executor
let job_storage = storage.clone();
let job_config = config.clone();
let job_transcode = transcode_service.clone();
let job_queue = pinakes_core::jobs::JobQueue::new(
config.jobs.worker_count,
move |job_id, kind, cancel, jobs| {
let storage = job_storage.clone();
let config = job_config.clone();
let transcode_svc = job_transcode.clone();
tokio::spawn(async move {
use pinakes_core::jobs::{JobKind, JobQueue};
let result = match kind {
match kind {
JobKind::Scan { path } => {
let ignore = config.scanning.ignore_patterns.clone();
let res = if let Some(p) = path {
@ -232,7 +244,7 @@ async fn main() -> Result<()> {
match storage.get_media(*mid).await {
Ok(item) => {
let source = item.path.clone();
let mt = item.media_type;
let mt = item.media_type.clone();
let id = item.id;
let td = thumb_dir.clone();
let tc = thumb_config.clone();
@ -333,8 +345,65 @@ async fn main() -> Result<()> {
Err(e) => JobQueue::fail(&jobs, job_id, e.to_string()).await,
}
}
JobKind::Transcode { media_id, profile } => {
if let Some(ref svc) = transcode_svc {
match storage.get_media(media_id).await {
Ok(item) => {
match svc
.start_transcode(
media_id,
&item.path,
&profile,
item.duration_secs,
&storage,
)
.await
{
Ok(session_id) => {
JobQueue::complete(
&jobs,
job_id,
serde_json::json!({"session_id": session_id.to_string()}),
)
.await;
}
Err(e) => {
JobQueue::fail(&jobs, job_id, e.to_string()).await
}
}
}
Err(e) => JobQueue::fail(&jobs, job_id, e.to_string()).await,
}
} else {
JobQueue::fail(&jobs, job_id, "transcoding is not enabled".to_string())
.await;
}
}
JobKind::Enrich { media_ids } => {
// Enrichment job placeholder
JobQueue::complete(
&jobs,
job_id,
serde_json::json!({"media_ids": media_ids.len(), "status": "not_implemented"}),
)
.await;
}
JobKind::CleanupAnalytics => {
let before = chrono::Utc::now() - chrono::Duration::days(90);
match storage.cleanup_old_events(before).await {
Ok(count) => {
JobQueue::complete(
&jobs,
job_id,
serde_json::json!({"cleaned_up": count}),
)
.await;
}
Err(e) => JobQueue::fail(&jobs, job_id, e.to_string()).await,
}
}
};
let _ = result;
();
drop(cancel);
})
},
@ -345,6 +414,27 @@ async fn main() -> Result<()> {
config.jobs.cache_ttl_secs,
));
// Initialize plugin manager if plugins are enabled (before moving config into Arc)
let plugin_manager = if config.plugins.enabled {
match pinakes_core::plugin::PluginManager::new(
config.plugins.data_dir.clone(),
config.plugins.cache_dir.clone(),
config.plugins.clone().into(),
) {
Ok(pm) => {
tracing::info!("Plugin manager initialized");
Some(Arc::new(pm))
}
Err(e) => {
tracing::warn!("Failed to initialize plugin manager: {}", e);
None
}
}
} else {
tracing::info!("Plugins disabled in configuration");
None
};
// Initialize scheduler with cancellation support
let shutdown_token = tokio_util::sync::CancellationToken::new();
let config_arc = Arc::new(RwLock::new(config));
@ -376,6 +466,8 @@ async fn main() -> Result<()> {
job_queue,
cache,
scheduler,
plugin_manager,
transcode_service,
};
// Periodic session cleanup (every 15 minutes)