mirror of
https://github.com/euzu/tuliprox.git
synced 2026-10-29 02:02:23 +01:00
hls reverse proxy implemented
This commit is contained in:
@@ -4,6 +4,7 @@ use crate::api::model::active_provider_manager::ActiveProviderManager;
|
||||
use crate::api::model::active_user_manager::ActiveUserManager;
|
||||
use crate::api::model::download::DownloadQueue;
|
||||
use crate::api::model::event_manager::EventManager;
|
||||
use crate::api::model::hls_cache::HlsCache;
|
||||
use crate::api::model::streams::shared_stream_manager::SharedStreamManager;
|
||||
use crate::model::config::{Config};
|
||||
use crate::model::hdhomerun_config::HdHomeRunDeviceConfig;
|
||||
@@ -16,6 +17,7 @@ pub struct AppState {
|
||||
pub http_client: Arc<reqwest::Client>,
|
||||
pub downloads: Arc<DownloadQueue>,
|
||||
pub cache: Arc<Option<Mutex<LRUResourceCache>>>,
|
||||
pub hls_cache: Arc<HlsCache>,
|
||||
pub shared_stream_manager: Arc<SharedStreamManager>,
|
||||
pub active_users: Arc<ActiveUserManager>,
|
||||
pub active_provider: Arc<ActiveProviderManager>,
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
use log::error;
|
||||
use std::collections::HashMap;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use chrono::Local;
|
||||
use cron::Schedule;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::time::Instant;
|
||||
use crate::utils::sys_utils::exit;
|
||||
use crate::model::hls::HlsEntry;
|
||||
|
||||
const EXPIRE_DURATION: u64 = 600; // 10 minutes
|
||||
|
||||
fn start_garbage_collector(cache: &Arc<HlsCache>) {
|
||||
let cache_clone = cache.clone();
|
||||
tokio::spawn(async move {
|
||||
match Schedule::from_str("0 */15 * * * * *") {
|
||||
Ok(schedule) => {
|
||||
let offset = *Local::now().offset();
|
||||
loop {
|
||||
let mut upcoming = schedule.upcoming(offset).take(1);
|
||||
if let Some(datetime) = upcoming.next() {
|
||||
tokio::time::sleep_until(tokio::time::Instant::from(crate::api::scheduler::datetime_to_instant(datetime))).await;
|
||||
cache_clone.gc().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => exit!("Failed to start scheduler: {}", err)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub struct HlsCache {
|
||||
pub entries: RwLock<HashMap<String, HlsEntry>>,
|
||||
}
|
||||
|
||||
impl HlsCache {
|
||||
pub fn garbage_collected() -> Arc<Self> {
|
||||
let cache = Arc::new(Self {
|
||||
entries: RwLock::new(HashMap::new()),
|
||||
});
|
||||
|
||||
start_garbage_collector(&cache);
|
||||
cache
|
||||
}
|
||||
|
||||
pub async fn add_entry(&self, entry: HlsEntry) {
|
||||
self.entries.write().await.insert(entry.token.to_string(), entry);
|
||||
}
|
||||
|
||||
pub async fn get_entry(&self, token: &str) -> Option<HlsEntry>{
|
||||
self.entries.read().await.get(token).cloned()
|
||||
}
|
||||
|
||||
pub async fn gc(&self) {
|
||||
let threshold = Instant::now() - Duration::from_secs(EXPIRE_DURATION);
|
||||
// Remove all expired elements
|
||||
self.entries.write().await.retain(|_, entry| entry.ts > threshold);
|
||||
}
|
||||
}
|
||||
@@ -9,3 +9,4 @@ pub(crate) mod streams;
|
||||
pub(in crate::api) mod active_user_manager;
|
||||
pub(in crate::api) mod active_provider_manager;
|
||||
pub(in crate::api) mod event_manager;
|
||||
pub(in crate::api) mod hls_cache;
|
||||
|
||||
@@ -421,7 +421,7 @@ pub async fn create_provider_stream(cfg: &Config,
|
||||
// use std::sync::Arc;
|
||||
// use crate::model::config::Config;
|
||||
//
|
||||
// #[actix_rt::test]
|
||||
// #[tokio::test]
|
||||
// async fn test_stream() {
|
||||
// let app = App::new().route("/test", web::get().to(test_stream_handler));
|
||||
// let server = test::init_service(app).await;
|
||||
|
||||
Reference in New Issue
Block a user