Moka cache eviction

[UPDATED TO ADD]

I'm playing with invalidate_entries_if(). I'd tried it earlier, but couldn't get it to compile. Compiles now, so I'll play with that.

Hi,
I'm trying to solve the problem of recording 4 reported personal activities over a month.
Each activity has a start time and two durations: timeout, duration to next activity.

The cache must persist across image activation.

I've chosen moka cache to implement this requirement. The cache key is phone+activity token, the cache value is duration to next activity.
This value is entry time to live. Activity timeout is time to idle.

My question is how to successfully perform cache eviction in the following test. It's currently failing.

Thanks for any insight you can provide.

fn ac_scen_010() {
    let ac = ActivityContext::new(true);

    let sms = Phone::from("15205551212");

    ac.put(&sms, "START", &Some(&MOCK_28_DAYS));
    std::thread::sleep(*MOCK_29_DAYS);
    assert_eq!(false, ac.exists(&sms, "START")); // cache.get()
}

MOCK_* is to handle not actually waiting 28 days. There is a MOCK_* version of the TTI table.

Because I have entry specific timeouts, I cannot use the builder() methods.
I've been trying to implement the Expiry trait. When creating an entry, TTL is considered. This is working. When the cache is restored from disk, each entry is expired if it has expired while at rest.

expire_after_read() is the problem child. It seems to work erratically. When current_time_elapsed is 8s, and tti is 2ms, the entry is not evicted.

/*
** ttl_duration: Sets the time to live of the activity.
 An activity will be expired after the specified duration past from insert.
*/
lazy_static! {
    pub static ref  TTL: Vec<Duration> = vec![
    *FIVE_MIN,         // Stop
    *TWENTYEIGHT_DAYS, // Start
    *FIVE_MIN,         // Help
    *SIX_HOURS,        // Point
];
}

/*
** tti_duration: Sets the time to idle of the activity.
** An activity will be expired after the specified duration past from get or insert.
*/
lazy_static! {
    pub static ref  TTI: Vec<Duration> = vec![
    *FIVE_MIN, // Stop
    *TWO_DAYS, // Start
    *FIVE_MIN, // Help
    *TWO_DAYS, // Point
];
}

fn expire_after_create(
    &self,
    activity: &Activity,
    activity_ttl: &Duration,
    current_time: Instant,
    ) -> Option<Duration> {
    let expire = current_time.elapsed()
        .checked_sub(*activity_ttl)
        .unwrap_or(Duration::default());

    return match activity.token.clone() {
        TokenKind::Point(_) | TokenKind::Stop | TokenKind::Help | TokenKind::Start => {
            Some(expire)
        }
        TokenKind::Unknown => Some(Duration::default()),
    };
    None
    }

#[allow(unused_variables)]
fn expire_after_read(
        &self,
        activity: &Activity,
        activity_ttl: &Duration,
        current_time: Instant,
        current_duration: Option<Duration>,
        last_modified_at: Instant,
    ) -> Option<Duration> {
        let mut current_time_elapsed = current_time.elapsed();
        let tti = match activity.token.clone() {
            TokenKind::Point(_) | TokenKind::Stop | TokenKind::Help | TokenKind::Start => {
                    TTI[usize::from(&activity.token)]
                }
            }
            TokenKind::Unknown => Duration::default(),
        };

        let retval = if current_time_elapsed > *activity_ttl {
            Some(tti)
        } else {
            current_duration
        };

        println!(
            "activity: {:?}, current_time: {:?} activity_ttl: {:?} current_duration: {:?} tti: {:?} retval: {:?}\n",
            activity.token,
            current_time_elapsed, activity_ttl, current_duration, tti, retval,
        );

        return retval;
    }

It works using the Expiry trait.
Here's a test that describes what I'm looking for

    fn ac_scen_040() {
        let ac = ActivityContext::new(true);

        let sms = Phone::from("15205551212");
        ac.put(&sms, "START");

        // Generate 2 Health actions/day for 7 days
        for _ in 0..6 {
            ac.put(&sms, "HEALTH");
            std::thread::sleep(*SIX_HRS);
            ac.put(&sms, "HEALTH");
            std::thread::sleep(*SIX_HRS);
        }

        assert_eq!(true, ac.exists(&sms, "START"));
        assert_eq!(true, ac.exists(&sms, "HEALTH"));
    }

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.