Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using ExpirationMode.ImmediateEviction ignores sliding expiration value #156

Open
ExLuzZziVo opened this issue Jun 15, 2021 · 7 comments
Open
Labels

Comments

@ExLuzZziVo
Copy link

Describe the bug
Hi, I am trying to use ExpirationMode.ImmediateEviction with sliding expiration in my project and this makes the entry to update every time I access it, ignoring the sliding expiration value

To Reproduce

            for (var i = 1; i <= 5; i++)
            {
                await _cache.GetOrAddAsync("1", entry => Task.FromResult(new Random().Next(1, 10)),
                    new LazyCacheEntryOptions {ExpirationMode = ExpirationMode.ImmediateEviction}
                        .SetSlidingExpiration(TimeSpan.FromSeconds(5))
                        .RegisterPostEvictionCallback((key, value, reason, state) =>
                        {
                            Debug.WriteLine($"{key} {((Task<int>) value).Result}");
                        }));
            }

Expected behavior
The sliding expiration time shouldn't be ignored

** Framework and Platform

  • OS: Windows 10 21H1
  • Framework: netcoreapp3.1
  • LazyCache Version: 2.1.3
@ExLuzZziVo ExLuzZziVo added the bug label Jun 15, 2021
@alastairtree
Copy link
Owner

alastairtree commented Jun 18, 2021

I suspect the bug is because the immediate expiration stuff was never tested with sliding expiration. Looking at https://github.com/alastairtree/LazyCache/blob/master/LazyCache/Providers/MemoryCacheProvider.cs#L55 you can see it seems to cancel based on absolute expiration so some additional code would be needed detect sliding to make it work.

expiryTokenSource.CancelAfter(lazyPolicy.ImmediateAbsoluteExpirationRelativeToNow);

and note the related code in https://github.com/alastairtree/LazyCache/blob/master/LazyCache/MemoryCacheEntryOptionsExtensions.cs

@alastairtree
Copy link
Owner

Just released a new version, may well fix this. Let us know how you get on?

Install-Package LazyCache -Version 2.4.0

@ExLuzZziVo
Copy link
Author

ExLuzZziVo commented Sep 2, 2021

Just released a new version, may well fix this. Let us know how you get on?

Install-Package LazyCache -Version 2.4.0

Unfortunately this doesn't fix it

A workaround is to use MemoryCacheEntryOptions instead of LazyCacheEntryOptions

@LukeRH
Copy link

LukeRH commented Sep 3, 2021

Hi @ExLuzZziVo, i am also seeing this issue please could you detail the workaround ?

@alastairtree
Copy link
Owner

A PR with a failing unit test would help track this down if you are willing?

@ExLuzZziVo
Copy link
Author

Hi @ExLuzZziVo, i am also seeing this issue please could you detail the workaround ?

Just replace new LazyCacheEntryOptions {ExpirationMode = ExpirationMode.ImmediateEviction} with new MemoryCacheEntryOptions() in above example and it will work as expected

A PR with a failing unit test would help track this down if you are willing?

I will try to make a PR next week

@ExLuzZziVo
Copy link
Author

@alastairtree There is a strange thing with the unit test for this issue. If I run the test method separately, it fails. If I run all the tests, it passes. I have tried to set the cache key manually but the result was the same.
My test method:

        [Test]
        public void GetFromCacheTwiceAtSameTimeOnlyAddsOnceWithSliding()
        {
            var times = 0;

            var lazyCacheEntryOptions = new LazyCacheEntryOptions { ExpirationMode = ExpirationMode.ImmediateEviction }
                .SetSlidingExpiration(TimeSpan.FromSeconds(20));

            var t1 = Task.Factory.StartNew(() =>
            {
                sut.GetOrAdd(TestKey, () =>
                {
                    Interlocked.Increment(ref times);
                    return new DateTime(2001, 01, 01);
                }, lazyCacheEntryOptions);
            });

            var t2 = Task.Factory.StartNew(() =>
            {
                sut.GetOrAdd(TestKey, () =>
                {
                    Interlocked.Increment(ref times);
                    return new DateTime(2001, 01, 01);
                }, lazyCacheEntryOptions);
            });

            Task.WaitAll(t1, t2);

            Assert.AreEqual(1, times);
        }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants