flaresolverr session cycling
This commit is contained in:
@@ -39,6 +39,7 @@ chrono = "0.4.44"
|
|||||||
md5 = "0.8.0"
|
md5 = "0.8.0"
|
||||||
|
|
||||||
[lints.rust]
|
[lints.rust]
|
||||||
|
warnings = "deny"
|
||||||
unexpected_cfgs = "allow"
|
unexpected_cfgs = "allow"
|
||||||
# Or keep it as a warning but whitelist the cfg:
|
# Or keep it as a warning but whitelist the cfg:
|
||||||
# unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_error_description_deprecated)'] }
|
# unexpected_cfgs = { level = "warn", check-cfg = ['cfg(has_error_description_deprecated)'] }
|
||||||
|
|||||||
2
build.rs
2
build.rs
@@ -1,3 +1,5 @@
|
|||||||
|
#![deny(warnings)]
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|||||||
@@ -172,8 +172,8 @@ impl SextbProvider {
|
|||||||
|
|
||||||
fn build_channel(&self, _clientversion: ClientVersion) -> Channel {
|
fn build_channel(&self, _clientversion: ClientVersion) -> Channel {
|
||||||
let genres = self.genres.read().map(|value| value.clone()).unwrap_or_default();
|
let genres = self.genres.read().map(|value| value.clone()).unwrap_or_default();
|
||||||
let studios = self.studios.read().map(|value| value.clone()).unwrap_or_default();
|
let _studios = self.studios.read().map(|value| value.clone()).unwrap_or_default();
|
||||||
let actresses = self
|
let _actresses = self
|
||||||
.actresses
|
.actresses
|
||||||
.read()
|
.read()
|
||||||
.map(|value| value.clone())
|
.map(|value| value.clone())
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ struct DetailResponse {
|
|||||||
related_searches: Option<Vec<String>>,
|
related_searches: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct DetailVideo {
|
struct DetailVideo {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -152,6 +153,7 @@ struct DetailVideo {
|
|||||||
related_searches: Option<Vec<String>>,
|
related_searches: Option<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct DetailStatistics {
|
struct DetailStatistics {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -164,6 +166,7 @@ struct DetailStatistics {
|
|||||||
dislikes: i64,
|
dislikes: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct DetailUser {
|
struct DetailUser {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -176,12 +179,14 @@ struct DetailUser {
|
|||||||
subscribers_count: String,
|
subscribers_count: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct DetailChannel {
|
struct DetailChannel {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
title: String,
|
title: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct DetailCategory {
|
struct DetailCategory {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -228,6 +233,7 @@ struct MembersResponse {
|
|||||||
members: Vec<MemberSummary>,
|
members: Vec<MemberSummary>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct MemberSummary {
|
struct MemberSummary {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -240,6 +246,7 @@ struct MemberSummary {
|
|||||||
statistics: MemberStatistics,
|
statistics: MemberStatistics,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[derive(Debug, Deserialize, Clone, Default)]
|
#[derive(Debug, Deserialize, Clone, Default)]
|
||||||
struct MemberStatistics {
|
struct MemberStatistics {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
use std::{collections::HashMap, env};
|
use std::{collections::HashMap, env, sync::Arc};
|
||||||
|
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
use tokio::sync::Mutex;
|
||||||
use wreq::{Client, Proxy};
|
use wreq::{Client, Proxy};
|
||||||
use wreq_util::Emulation;
|
use wreq_util::Emulation;
|
||||||
|
|
||||||
@@ -51,11 +52,22 @@ pub struct FlareSolverrResponse {
|
|||||||
pub version: String,
|
pub version: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Flaresolverr {
|
pub struct Flaresolverr {
|
||||||
url: String,
|
url: String,
|
||||||
proxy: bool,
|
proxy: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct SessionState {
|
||||||
|
ready_session: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn global_session_state() -> &'static Arc<Mutex<SessionState>> {
|
||||||
|
static STATE: std::sync::OnceLock<Arc<Mutex<SessionState>>> = std::sync::OnceLock::new();
|
||||||
|
STATE.get_or_init(|| Arc::new(Mutex::new(SessionState::default())))
|
||||||
|
}
|
||||||
|
|
||||||
impl Flaresolverr {
|
impl Flaresolverr {
|
||||||
pub fn new(url: String) -> Self {
|
pub fn new(url: String) -> Self {
|
||||||
Self { url, proxy: false }
|
Self { url, proxy: false }
|
||||||
@@ -144,18 +156,64 @@ impl Flaresolverr {
|
|||||||
Ok(typed)
|
Ok(typed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn ensure_ready_session_locked(
|
||||||
|
&self,
|
||||||
|
state: &mut SessionState,
|
||||||
|
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
|
if let Some(existing) = state.ready_session.clone() {
|
||||||
|
return Ok(existing);
|
||||||
|
}
|
||||||
|
let created = self.create_session().await?;
|
||||||
|
state.ready_session = Some(created.clone());
|
||||||
|
Ok(created)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn solve(
|
pub async fn solve(
|
||||||
&self,
|
&self,
|
||||||
request: FlareSolverrRequest,
|
request: FlareSolverrRequest,
|
||||||
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error + Send + Sync>> {
|
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||||
let session = self.create_session().await?;
|
// Keep one ready session globally and rotate it per solve:
|
||||||
let result = self.solve_with_session(request, &session).await;
|
// - solve with current ready session
|
||||||
if let Err(error) = self.destroy_session(&session).await {
|
// - create replacement session in parallel
|
||||||
|
// - destroy old session
|
||||||
|
// - keep replacement as new ready session
|
||||||
|
let session_state = global_session_state().clone();
|
||||||
|
let mut state = session_state.lock().await;
|
||||||
|
let active_session = self.ensure_ready_session_locked(&mut state).await?;
|
||||||
|
|
||||||
|
let replacement_creator = {
|
||||||
|
let solver = self.clone();
|
||||||
|
tokio::spawn(async move { solver.create_session().await })
|
||||||
|
};
|
||||||
|
|
||||||
|
let solve_result = self.solve_with_session(request, &active_session).await;
|
||||||
|
|
||||||
|
let replacement_session = match replacement_creator.await {
|
||||||
|
Ok(Ok(session)) => session,
|
||||||
|
Ok(Err(error)) => {
|
||||||
|
eprintln!(
|
||||||
|
"FlareSolverr replacement session creation failed, retrying inline: {}",
|
||||||
|
error
|
||||||
|
);
|
||||||
|
self.create_session().await?
|
||||||
|
}
|
||||||
|
Err(join_error) => {
|
||||||
|
eprintln!(
|
||||||
|
"FlareSolverr replacement task join failed, retrying inline: {}",
|
||||||
|
join_error
|
||||||
|
);
|
||||||
|
self.create_session().await?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Err(error) = self.destroy_session(&active_session).await {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"FlareSolverr session cleanup failed for session '{}': {}",
|
"FlareSolverr session cleanup failed for session '{}': {}",
|
||||||
session, error
|
active_session, error
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
result
|
|
||||||
|
state.ready_session = Some(replacement_session);
|
||||||
|
solve_result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user