126 lines
4.5 KiB
Rust
126 lines
4.5 KiB
Rust
//! Boucle de polling replay.
|
|
//!
|
|
//! Poll le serveur toutes les secondes pour recuperer les actions a executer.
|
|
//! Quand une action est recue, l'execute via executor et rapporte le resultat.
|
|
//! Gere le backoff exponentiel en cas d'indisponibilite du serveur.
|
|
//!
|
|
//! Reproduit le comportement de _replay_poll_loop dans agent_v1/main.py.
|
|
|
|
use crate::capture;
|
|
use crate::config::Config;
|
|
use crate::executor;
|
|
use crate::network;
|
|
use crate::notifications;
|
|
use crate::state::AgentState;
|
|
use reqwest::blocking::Client;
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
|
|
/// Boucle de polling replay (tourne dans un thread dedie).
|
|
///
|
|
/// - Poll GET /replay/next toutes les secondes
|
|
/// - Execute l'action via executor
|
|
/// - Capture un screenshot post-action
|
|
/// - Rapporte le resultat via POST /replay/result
|
|
/// - Backoff exponentiel si le serveur est indisponible
|
|
pub fn replay_poll_loop(config: &Config, state: &AgentState) {
|
|
let client = Client::new();
|
|
let mut poll_count: u64 = 0;
|
|
let backoff = config.replay_poll_interval_s;
|
|
let _backoff_max = 30.0_f64;
|
|
let _backoff_factor = 1.5_f64;
|
|
let mut replay_active = false;
|
|
|
|
println!(
|
|
"[REPLAY] Boucle replay demarree — poll toutes les {:.0}s sur {}",
|
|
config.replay_poll_interval_s, config.server_url
|
|
);
|
|
|
|
while state.is_running() {
|
|
// Verifier l'arret d'urgence
|
|
if state
|
|
.emergency_stop
|
|
.load(std::sync::atomic::Ordering::SeqCst)
|
|
{
|
|
if replay_active {
|
|
println!("[REPLAY] ARRET D'URGENCE — replay interrompu");
|
|
replay_active = false;
|
|
state.set_replay_active(false);
|
|
}
|
|
thread::sleep(Duration::from_secs(1));
|
|
continue;
|
|
}
|
|
|
|
poll_count += 1;
|
|
|
|
// Log periodique toutes les 60s pour confirmer que la boucle tourne
|
|
let polls_per_minute = (60.0 / backoff).ceil() as u64;
|
|
if polls_per_minute > 0 && poll_count % polls_per_minute == 0 {
|
|
println!(
|
|
"[REPLAY] Poll #{} — session={} — serveur={}",
|
|
poll_count,
|
|
config.agent_session_id(),
|
|
config.server_url,
|
|
);
|
|
}
|
|
|
|
match network::poll_next_action(&client, config) {
|
|
Some(action) => {
|
|
if !replay_active {
|
|
replay_active = true;
|
|
state.set_replay_active(true);
|
|
notifications::replay_started("workflow");
|
|
println!("[REPLAY] Replay demarre");
|
|
}
|
|
|
|
let action_type = action.action_type.clone();
|
|
let action_id = action.action_id.clone();
|
|
println!(
|
|
"\n>>> REPLAY ACTION RECUE : {} (id={})",
|
|
action_type, action_id
|
|
);
|
|
|
|
// Obtenir les dimensions de l'ecran
|
|
let (sw, sh) = capture::screen_dimensions().unwrap_or((1920, 1080));
|
|
|
|
// Executer l'action (avec config pour la resolution visuelle)
|
|
println!(">>> Execution de l'action {}...", action_type);
|
|
let mut result = executor::execute_action(&action, sw, sh, config);
|
|
println!(
|
|
">>> Resultat execution : success={}, error={:?}",
|
|
result.success, result.error
|
|
);
|
|
|
|
// Capture screenshot post-action (apres 500ms)
|
|
thread::sleep(Duration::from_millis(500));
|
|
if let Some(img) = capture::capture_screenshot() {
|
|
let b64 = capture::screenshot_to_jpeg_base64(&img, 60);
|
|
if !b64.is_empty() {
|
|
result.screenshot = Some(b64);
|
|
}
|
|
}
|
|
|
|
// Rapporter le resultat au serveur (TOUJOURS, meme en erreur)
|
|
network::report_result(&client, config, &result);
|
|
|
|
// Poll plus rapidement pour enchainer les actions
|
|
thread::sleep(Duration::from_millis(200));
|
|
continue;
|
|
}
|
|
None => {
|
|
if replay_active {
|
|
println!("[REPLAY] Replay termine — retour en mode capture");
|
|
replay_active = false;
|
|
state.set_replay_active(false);
|
|
notifications::replay_finished(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
let sleep_duration = Duration::from_secs_f64(backoff);
|
|
thread::sleep(sleep_duration);
|
|
}
|
|
|
|
println!("[REPLAY] Boucle arretee.");
|
|
}
|