feature/hls-content-hash #95
@@ -80,8 +80,7 @@ pub async fn generate_video(
|
|||||||
return HttpResponse::BadRequest().finish();
|
return HttpResponse::BadRequest().finish();
|
||||||
};
|
};
|
||||||
|
|
||||||
let preferred_library =
|
let preferred_library = libraries::resolve_library_param(&app_state, body.library.as_deref())
|
||||||
libraries::resolve_library_param(&app_state, body.library.as_deref())
|
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()
|
.flatten()
|
||||||
.unwrap_or_else(|| app_state.primary_library());
|
.unwrap_or_else(|| app_state.primary_library());
|
||||||
@@ -122,7 +121,11 @@ pub async fn generate_video(
|
|||||||
// already-ingested videos.
|
// already-ingested videos.
|
||||||
let hash_from_db: Option<String> = {
|
let hash_from_db: Option<String> = {
|
||||||
let mut dao = exif_dao.lock().expect("Unable to lock ExifDao");
|
let mut dao = exif_dao.lock().expect("Unable to lock ExifDao");
|
||||||
match dao.get_exif_batch(&context, Some(resolved_library_id), &[rel_path.clone()]) {
|
match dao.get_exif_batch(
|
||||||
|
&context,
|
||||||
|
Some(resolved_library_id),
|
||||||
|
std::slice::from_ref(&rel_path),
|
||||||
|
) {
|
||||||
Ok(rows) => rows.into_iter().next().and_then(|r| r.content_hash),
|
Ok(rows) => rows.into_iter().next().and_then(|r| r.content_hash),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!(
|
warn!(
|
||||||
|
|||||||
@@ -256,9 +256,8 @@ pub async fn hls_stats_handler(
|
|||||||
|
|
||||||
// Synchronous file IO + DB query — run on a blocking pool so the
|
// Synchronous file IO + DB query — run on a blocking pool so the
|
||||||
// actix worker thread stays free for other requests.
|
// actix worker thread stays free for other requests.
|
||||||
let stats = match web::block(move || compute_and_publish(&libraries, &exif_dao, &video_dir))
|
let stats =
|
||||||
.await
|
match web::block(move || compute_and_publish(&libraries, &exif_dao, &video_dir)).await {
|
||||||
{
|
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("/hls/stats: blocking task failed: {:?}", e);
|
warn!("/hls/stats: blocking task failed: {:?}", e);
|
||||||
|
|||||||
@@ -38,10 +38,7 @@ pub struct RetireStats {
|
|||||||
|
|
||||||
impl RetireStats {
|
impl RetireStats {
|
||||||
pub fn total_deleted(&self) -> usize {
|
pub fn total_deleted(&self) -> usize {
|
||||||
self.deleted_playlists
|
self.deleted_playlists + self.deleted_segments + self.deleted_sentinels + self.deleted_tmp
|
||||||
+ self.deleted_segments
|
|
||||||
+ self.deleted_sentinels
|
|
||||||
+ self.deleted_tmp
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -79,9 +79,10 @@ pub fn cleanup_orphaned_playlists(
|
|||||||
info!(" Cleanup interval: {} seconds", cleanup_interval_secs);
|
info!(" Cleanup interval: {} seconds", cleanup_interval_secs);
|
||||||
info!(" HLS directory: {}", video_path.display());
|
info!(" HLS directory: {}", video_path.display());
|
||||||
|
|
||||||
let exif_dao: Arc<Mutex<Box<dyn ExifDao>>> = Arc::new(Mutex::new(
|
let exif_dao: Arc<Mutex<Box<dyn ExifDao>>> = Arc::new(Mutex::new(Box::new(
|
||||||
Box::new(SqliteExifDao::new()) as Box<dyn ExifDao>
|
SqliteExifDao::new(),
|
||||||
));
|
)
|
||||||
|
as Box<dyn ExifDao>));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
std::thread::sleep(Duration::from_secs(cleanup_interval_secs));
|
std::thread::sleep(Duration::from_secs(cleanup_interval_secs));
|
||||||
@@ -163,11 +164,7 @@ pub fn cleanup_orphaned_playlists(
|
|||||||
|
|
||||||
for shard_entry in read_root.flatten() {
|
for shard_entry in read_root.flatten() {
|
||||||
let shard_path = shard_entry.path();
|
let shard_path = shard_entry.path();
|
||||||
if !shard_entry
|
if !shard_entry.file_type().map(|t| t.is_dir()).unwrap_or(false) {
|
||||||
.file_type()
|
|
||||||
.map(|t| t.is_dir())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let shard_name = match shard_path.file_name().and_then(|n| n.to_str()) {
|
let shard_name = match shard_path.file_name().and_then(|n| n.to_str()) {
|
||||||
@@ -194,16 +191,14 @@ pub fn cleanup_orphaned_playlists(
|
|||||||
let mut shard_emptied = true;
|
let mut shard_emptied = true;
|
||||||
for hash_entry in read_shard.flatten() {
|
for hash_entry in read_shard.flatten() {
|
||||||
let hash_path = hash_entry.path();
|
let hash_path = hash_entry.path();
|
||||||
if !hash_entry
|
if !hash_entry.file_type().map(|t| t.is_dir()).unwrap_or(false) {
|
||||||
.file_type()
|
|
||||||
.map(|t| t.is_dir())
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
shard_emptied = false;
|
shard_emptied = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let Some(hash_name) =
|
let Some(hash_name) = hash_path
|
||||||
hash_path.file_name().and_then(|n| n.to_str()).map(|n| n.to_owned())
|
.file_name()
|
||||||
|
.and_then(|n| n.to_str())
|
||||||
|
.map(|n| n.to_owned())
|
||||||
else {
|
else {
|
||||||
shard_emptied = false;
|
shard_emptied = false;
|
||||||
continue;
|
continue;
|
||||||
@@ -586,13 +581,9 @@ pub fn watch_files(
|
|||||||
// quick scans because the cost is non-trivial on big
|
// quick scans because the cost is non-trivial on big
|
||||||
// libraries and the data only meaningfully changes on
|
// libraries and the data only meaningfully changes on
|
||||||
// full passes.
|
// full passes.
|
||||||
let video_dir_str =
|
let video_dir_str = dotenv::var("VIDEO_PATH").expect("VIDEO_PATH must be set");
|
||||||
dotenv::var("VIDEO_PATH").expect("VIDEO_PATH must be set");
|
let stats =
|
||||||
let stats = hls_stats::compute_and_publish(
|
hls_stats::compute_and_publish(&libs, &exif_dao, Path::new(&video_dir_str));
|
||||||
&libs,
|
|
||||||
&exif_dao,
|
|
||||||
Path::new(&video_dir_str),
|
|
||||||
);
|
|
||||||
hls_stats::log_summary(&stats);
|
hls_stats::log_summary(&stats);
|
||||||
|
|
||||||
last_full_scan = now;
|
last_full_scan = now;
|
||||||
|
|||||||
Reference in New Issue
Block a user