Skip to content

Conversation

@bitfaster
Copy link
Owner

@bitfaster bitfaster commented Nov 12, 2023

Implement a time-based eviction policy where the caller can specify the time to expire per item. The IExpiryCalculator interface enables the caller to evaluate both the key and the value to compute a TimeSpan that defines the time to expire:

public class Expiry : IExpiryCalculator<string, int>
{
    public TimeSpan GetExpireAfterCreate(string key, int value) => TimeSpan.FromSeconds(10);
    public TimeSpan GetExpireAfterRead(string key, int value, TimeSpan current) => current;
    public TimeSpan GetExpireAfterUpdate(string key, int value, TimeSpan current) => current;
}

ICache<string, int> expireAfter = new ConcurrentLruBuilder<string, int>()
   .WithExpireAfter(new Expiry())
   .Build();

This is the same API used by Caffeine.

The new policy is exposed on ICache via CachePolicy as a new Optional<IDiscreteTimePolicy> called ExpireAfter:

public class CachePolicy
{
    // ...
    public Optional<IBoundedPolicy> Eviction { get; }
    public Optional<ITimePolicy> ExpireAfterWrite { get; }
    public Optional<ITimePolicy> ExpireAfterAccess { get; }
    public Optional<IDiscreteTimePolicy> ExpireAfter { get; }
}

where IDiscreteTimePolicy is defined as

    public interface IDiscreteTimePolicy
    {
        bool TryGetTimeToExpire<K>(K key, out TimeSpan timeToExpire);
        void TrimExpired();
    }
  • There are two places where it would be a breaking change to get end to end generics:
    1. LruInfo does not know about value type, but IExpiry does. Therefore, internally store as object and use generic get and set methods to specify the expiry. The builder methods are typed, so this is largely hidden behind the builder.
    2. IVariableTimePolicy.TryGetTimeToLive() has key type as a generic method parameter, because Policy is not generic in terms of key or value.
  • WithExpireAfter is present only on ConcurrentLruBuilder and AsyncConcurrentLruBuilder
    • You can't call WithExpireAfter on AtomicAsyncConcurrentLruBuilder, AtomicConcurrentLruBuilder, AtomicScopedAsyncConcurrentLruBuilder, AtomicScopedConcurrentLruBuilder, ScopedAsyncConcurrentLruBuilder or ScopedConcurrentLruBuilder.
    • It is still possible to call WithExpireAfter, then call an As method to change the builder type. The above builders all have guards in the build method to throw a runtime exception in this case.

@bitfaster bitfaster changed the title ConcurrentLru expire after eviction policy ConcurrentLru expire after variable eviction policy Nov 12, 2023
@coveralls
Copy link

coveralls commented Nov 12, 2023

Coverage Status

coverage: 98.652% (-0.06%) from 98.708%
when pulling 6c7b370 on users/alexpeck/variablepolicy
into 530368e on main.

@bitfaster bitfaster changed the title ConcurrentLru expire after variable eviction policy ConcurrentLru item based time eviction policy Nov 14, 2023
@bitfaster bitfaster marked this pull request as ready for review November 15, 2023 04:41
@bitfaster bitfaster merged commit b3891ea into main Nov 15, 2023
@bitfaster bitfaster deleted the users/alexpeck/variablepolicy branch November 15, 2023 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature request] individual items expiry Expiration based on a Value's property?

3 participants