feat: easy captcha update job runner

This commit is contained in:
Aravinth Manivannan 2024-01-05 01:03:38 +05:30
parent 790fd8f393
commit 239e0bfd47
No known key found for this signature in database
GPG key ID: F8F50389936984FF
3 changed files with 156 additions and 5 deletions

View file

@ -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);

132
src/easy.rs Normal file
View file

@ -0,0 +1,132 @@
// Copyright (C) 2024// Copyright (C) 2024 Aravinth Manivannan <realaravinth@batsense.net>
// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
//
// 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<JoinHandle<()>> {
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)
}
}

View file

@ -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();
}