wb-cache 0.1.0

Your L1 in-app write-behind cache for various kinds of backends.
Documentation
use fieldx::fxstruct;
use rand_distr::Distribution;
use rand_distr::Gamma;
use rand_distr::Poisson;

use crate::test::simulation::db::entity::Customer as DbCustomer;
use crate::test::simulation::types::simerr;
use crate::test::simulation::types::Result;

#[derive(Clone, Debug)]
#[fxstruct(no_new, builder(post_build), get)]
pub struct Customer {
    #[fieldx(copy)]
    pub id:            i32,
    pub first_name:    String,
    pub last_name:     String,
    pub email:         String,
    #[fieldx(copy, set, default(-1))]
    pub registered_on: i32,

    #[fieldx(copy)]
    erratic_quotient: f64,
    #[fieldx(copy)]
    orders_per_day:   f64,

    /// The Gamma for Negative Binomial distribution used to sample the number of items of this product sold to a single
    /// customer per day.
    #[fieldx(optional, builder(off), set(private), get("_nb_gamma", as_ref))]
    nb_gamma: Gamma<f64>,
}

impl Customer {
    fn post_build(mut self) -> Self {
        let eq = self.erratic_quotient();
        let shape = self.orders_per_day() / eq;
        self.set_nb_gamma(Gamma::new(shape, eq).unwrap());

        self
    }

    #[inline(always)]
    pub fn nb_gamma(&self) -> &Gamma<f64> {
        self._nb_gamma().unwrap()
    }

    pub fn daily_purchases(&self) -> Result<f64> {
        let mut rng = &mut rand::rng();
        let lambda = self.nb_gamma().sample(&mut rng);
        if lambda == 0. {
            return Ok(0.0);
        }
        Ok(Poisson::new(lambda)
            .map_err(|err| {
                let err = simerr!("Poisson(lambda={lambda}): {}", err);
                err.context(format!(
                    "Customer EQ: {}; orders per day: {}",
                    self.erratic_quotient(),
                    self.orders_per_day()
                ));
                err
            })?
            .sample(&mut rng) as f64)
    }
}

impl From<Customer> for DbCustomer {
    fn from(customer: Customer) -> Self {
        DbCustomer {
            id:            customer.id,
            first_name:    customer.first_name,
            last_name:     customer.last_name,
            email:         customer.email,
            registered_on: customer.registered_on,
        }
    }
}