From 239e0bfd47b2d63e80bd3d7e91e91eaa58d11f74 Mon Sep 17 00:00:00 2001 From: Aravinth Manivannan Date: Fri, 5 Jan 2024 01:03:38 +0530 Subject: [PATCH] feat: easy captcha update job runner --- src/demo.rs | 6 ++- src/easy.rs | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 23 +++++++-- 3 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 src/easy.rs diff --git a/src/demo.rs b/src/demo.rs index 66a2f562..b1ef9d74 100644 --- a/src/demo.rs +++ b/src/demo.rs @@ -28,7 +28,10 @@ pub struct DemoUser { } impl DemoUser { - pub async fn spawn(data: AppData, duration: u32) -> ServiceResult<(Self, JoinHandle<()>)> { + pub async fn spawn( + data: AppData, + duration: u32, + ) -> ServiceResult<(Self, JoinHandle<()>)> { let (tx, rx) = channel(); let handle = Self::run(data, duration, rx).await?; let d = Self { tx }; @@ -108,7 +111,6 @@ impl DemoUser { if let Err(e) = Self::register_demo_user(&data).await { log::error!("Error while registering demo user: {:?}", e); } - } }; let handle = spawn(fut); diff --git a/src/easy.rs b/src/easy.rs new file mode 100644 index 00000000..e6d880f1 --- /dev/null +++ b/src/easy.rs @@ -0,0 +1,132 @@ +// Copyright (C) 2024// Copyright (C) 2024 Aravinth Manivannan +// SPDX-FileCopyrightText: 2023 Aravinth Manivannan +// +// SPDX-License-Identifier: AGPL-3.0-or-later + +use std::time::Duration; +//use std::sync::atomicBool + +use actix::clock::sleep; +use actix::spawn; +use tokio::sync::oneshot::{channel, error::TryRecvError, Receiver, Sender}; +use tokio::task::JoinHandle; + +use crate::api::v1::mcaptcha::easy::{ + update_runner, TrafficPatternRequest, UpdateTrafficPattern, +}; +use crate::*; + +use errors::*; + +pub struct UpdateEasyCaptcha { + tx: Sender<()>, +} + +impl UpdateEasyCaptcha { + pub async fn spawn( + data: AppData, + duration: u32, + ) -> ServiceResult<(Self, JoinHandle<()>)> { + let (tx, rx) = channel(); + let handle = Self::run(data, duration, rx).await?; + let d = Self { tx }; + + Ok((d, handle)) + } + + #[allow(dead_code)] + pub fn abort(mut self) { + self.tx.send(()); + } + + /// update configurations + async fn update_captcha_configurations( + data: &AppData, + rx: &mut Receiver<()>, + ) -> ServiceResult<()> { + let limit = 10; + let mut offset = 0; + let mut page = 0; + loop { + offset = page * limit; + + if !Self::can_run(rx) { + return Ok(()); + } + + let mut patterns = data.db.get_all_easy_captchas(limit, offset).await?; + for pattern in patterns.drain(0..) { + if !Self::can_run(rx) { + return Ok(()); + } + + let publish_benchmarks = + data.db.analytics_captcha_is_published(&pattern.key).await?; + + let req = UpdateTrafficPattern { + pattern: TrafficPatternRequest { + avg_traffic: pattern.traffic_pattern.avg_traffic, + peak_sustainable_traffic: pattern + .traffic_pattern + .peak_sustainable_traffic, + broke_my_site_traffic: pattern + .traffic_pattern + .broke_my_site_traffic, + description: pattern.description, + publish_benchmarks, + }, + key: pattern.key, + }; + if !Self::can_run(rx) { + return Ok(()); + } + + update_runner(&data, req, pattern.username).await?; + } + page += 1; + } + } + + fn can_run(rx: &mut Receiver<()>) -> bool { + match rx.try_recv() { + Err(TryRecvError::Empty) => true, + _ => false, + } + } + + pub async fn run( + data: AppData, + duration: u32, + mut rx: Receiver<()>, + ) -> ServiceResult> { + let mut exit = false; + let fut = async move { + loop { + if exit { + break; + } + for _ in 0..duration { + if Self::can_run(&mut rx) { + sleep(Duration::new(1, 0)).await; + continue; + } else { + exit = true; + break; + } + } + + if let Some(err) = Self::update_captcha_configurations(&data, &mut rx) + .await + .err() + { + log::error!( + "Tried to update easy captcha configurations in background {:?}", + err + ); + } + } + }; + let handle = spawn(fut); + Ok(handle) + } +} diff --git a/src/main.rs b/src/main.rs index ddc4aa2e..2366a2b9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,9 +12,9 @@ use actix_web::{ error::InternalError, http::StatusCode, middleware as actix_middleware, web::JsonConfig, App, HttpServer, }; -use tokio::task::JoinHandle; use lazy_static::lazy_static; use log::info; +use tokio::task::JoinHandle; mod api; mod data; @@ -22,6 +22,7 @@ mod date; mod db; mod demo; mod docs; +mod easy; mod email; mod errors; #[macro_use] @@ -114,8 +115,19 @@ async fn main() -> std::io::Result<()> { let mut demo_user: Option<(DemoUser, JoinHandle<()>)> = None; if settings.allow_demo && settings.allow_registration { - demo_user = Some( - DemoUser::spawn(data.clone(), 60 * 30) + demo_user = Some(DemoUser::spawn(data.clone(), 60 * 30).await.unwrap()); + } + + let mut update_easy_captcha: Option<(easy::UpdateEasyCaptcha, JoinHandle<()>)> = + None; + if settings + .captcha + .default_difficulty_strategy + .avg_traffic_time + .is_some() + { + update_easy_captcha = Some( + easy::UpdateEasyCaptcha::spawn(data.clone(), 60 * 30) .await .unwrap(), ); @@ -161,6 +173,11 @@ async fn main() -> std::io::Result<()> { demo_user.1.await.unwrap(); } + if let Some(update_easy_captcha) = update_easy_captcha { + update_easy_captcha.0.abort(); + update_easy_captcha.1.await.unwrap(); + } + if let Some(survey_upload_handle) = survey_upload_handle { survey_upload_handle.await.unwrap(); }