flaresolverr session cycling
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
use std::{collections::HashMap, env};
|
||||
use std::{collections::HashMap, env, sync::Arc};
|
||||
|
||||
use serde_json::json;
|
||||
use serde_json::Value;
|
||||
use tokio::sync::Mutex;
|
||||
use wreq::{Client, Proxy};
|
||||
use wreq_util::Emulation;
|
||||
|
||||
@@ -51,11 +52,22 @@ pub struct FlareSolverrResponse {
|
||||
pub version: String,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Flaresolverr {
|
||||
url: String,
|
||||
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 {
|
||||
pub fn new(url: String) -> Self {
|
||||
Self { url, proxy: false }
|
||||
@@ -144,18 +156,64 @@ impl Flaresolverr {
|
||||
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(
|
||||
&self,
|
||||
request: FlareSolverrRequest,
|
||||
) -> Result<FlareSolverrResponse, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let session = self.create_session().await?;
|
||||
let result = self.solve_with_session(request, &session).await;
|
||||
if let Err(error) = self.destroy_session(&session).await {
|
||||
// Keep one ready session globally and rotate it per solve:
|
||||
// - solve with current ready session
|
||||
// - 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!(
|
||||
"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