#
mcaptcha/
stats.rs

    1// Copyright (C) 2022  Aravinth Manivannan <realaravinth@batsense.net>
    2// SPDX-FileCopyrightText: 2023 Aravinth Manivannan <realaravinth@batsense.net>
    3//
    4// SPDX-License-Identifier: AGPL-3.0-or-later
    5
    6use async_trait::async_trait;
    7use db_core::errors::DBResult;
    8use serde::{Deserialize, Serialize};
    9
    10use crate::data::Data;
    11
    12#[async_trait]
    13pub trait Stats: std::marker::Send + std::marker::Sync + CloneStats {
    14    /// record PoWConfig fetches
    15    async fn record_fetch(&self, d: &Data, key: &str) -> DBResult<()>;
    16
    17    /// record PoWConfig solves
    18    async fn record_solve(&self, d: &Data, key: &str) -> DBResult<()>;
    19
    20    /// record PoWConfig confirms
    21    async fn record_confirm(&self, d: &Data, key: &str) -> DBResult<()>;
    22
    23    /// fetch stats
    24    async fn fetch(&self, d: &Data, user: &str, key: &str) -> DBResult<CaptchaStats>;
    25}
    26
    27/// Trait to clone MCDatabase
    28pub trait CloneStats {
    29    /// clone DB
    30    fn clone_stats(&self) -> Box<dyn Stats>;
    31}
    32
    33impl<T> CloneStats for T
    34where
    35    T: Stats + Clone + 'static,
    36{
    37    fn clone_stats(&self) -> Box<dyn Stats> {
    38        Box::new(self.clone())
    39    }
    40}
    41
    42//impl Clone for Box<dyn CloneStats> {
    43//    fn clone(&self) -> Self {
    44//        Box::clone(self)
    45//        //(*self).clone_stats()
    46//    }
    47//}
    48
    49#[derive(Debug, Default, PartialEq, Clone, Deserialize, Serialize)]
    50pub struct CaptchaStats {
    51    pub config_fetches: Vec<i64>,
    52    pub solves: Vec<i64>,
    53    pub confirms: Vec<i64>,
    54}
    55
    56#[derive(Clone, Default, PartialEq, Debug)]
    57pub struct Real;
    58
    59#[async_trait]
    60impl Stats for Real {
    61    /// record PoWConfig fetches
    62    async fn record_fetch(&self, d: &Data, key: &str) -> DBResult<()> {
    63        d.db.record_fetch(key).await
    64    }
    65
    66    /// record PoWConfig solves
    67    async fn record_solve(&self, d: &Data, key: &str) -> DBResult<()> {
    68        d.db.record_solve(key).await
    69    }
    70
    71    /// record PoWConfig confirms
    72    async fn record_confirm(&self, d: &Data, key: &str) -> DBResult<()> {
    73        d.db.record_confirm(key).await
    74    }
    75
    76    /// fetch stats
    77    async fn fetch(&self, d: &Data, user: &str, key: &str) -> DBResult<CaptchaStats> {
    78        let config_fetches_fut = d.db.fetch_config_fetched(user, key);
    79        let solves_fut = d.db.fetch_solve(user, key);
    80        let confirms_fut = d.db.fetch_confirm(user, key);
    81
    82        let (config_fetches, solves, confirms) =
    83            futures::try_join!(config_fetches_fut, solves_fut, confirms_fut)?;
    84
    85        let res = CaptchaStats {
    86            config_fetches,
    87            solves,
    88            confirms,
    89        };
    90
    91        Ok(res)
    92    }
    93}
    94
    95#[derive(Clone, Default, PartialEq, Debug)]
    96pub struct Dummy;
    97
    98#[async_trait]
    99impl Stats for Dummy {
    100    /// record PoWConfig fetches
    101    async fn record_fetch(&self, _: &Data, _: &str) -> DBResult<()> {
    102        Ok(())
    103    }
    104
    105    /// record PoWConfig solves
    106    async fn record_solve(&self, _: &Data, _: &str) -> DBResult<()> {
    107        Ok(())
    108    }
    109
    110    /// record PoWConfig confirms
    111    async fn record_confirm(&self, _: &Data, _: &str) -> DBResult<()> {
    112        Ok(())
    113    }
    114
    115    /// fetch stats
    116    async fn fetch(&self, _: &Data, _: &str, _: &str) -> DBResult<CaptchaStats> {
    117        Ok(CaptchaStats::default())
    118    }
    119}