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

[BUG] RemoveByTagAsync does not work when SkipMemoryCacheWrite = true #419

Open
sebbarg opened this issue Mar 6, 2025 · 1 comment
Open

Comments

@sebbarg
Copy link

sebbarg commented Mar 6, 2025

Describe the bug

When setting SkipMemoryCacheWrite = true (and optionally also SkipMemoryCacheRead = true), RemoveByTagAsync does not remove tagged entries from level 2 cache.

To Reproduce

    [Test, Explicit]
    public async Task ItShould()
    {
        const bool bypassMemory = true;

        var services = new ServiceCollection();

        services.AddLogging(logging =>
        {
            logging.AddConsole();
            logging.SetMinimumLevel(LogLevel.Debug);
        });

        services.AddFusionCache()
            .WithSerializer(
                new FusionCacheSystemTextJsonSerializer()
            )
            .WithDistributedCache(
                new RedisCache(new RedisCacheOptions { Configuration = _redisContainer!.GetConnectionString() })
            );

        var serviceProvider = services.BuildServiceProvider();

        var cache = serviceProvider.GetRequiredService<IFusionCache>();
        var tags = new[] { "foo" };

        var id = Guid.NewGuid();
        var key = $"TheKey:{id}";
        var value = await GetProductFromDbAsync(id); // This is just a simulation that creates a simple POCO

        // Create cache entry with tags
        await cache.SetAsync(key, value,
            setupAction =>
            {
                setupAction.SkipMemoryCacheRead = bypassMemory;
                setupAction.SkipMemoryCacheWrite = bypassMemory;
            },
            tags);

        // Ensure it's retrievable
        var record2 = await cache.GetOrDefaultAsync<PocoA?>(key,
            setupAction =>
            {
                setupAction.SkipMemoryCacheRead = bypassMemory;
                setupAction.SkipMemoryCacheWrite = bypassMemory;
            });
        Assert.That(record2, Is.Not.Null);

        // For good measure
        await Task.Delay(200);

        await cache.RemoveByTagAsync("foo",
            new FusionCacheEntryOptions
            {
                SkipMemoryCacheRead = bypassMemory,
                SkipMemoryCacheWrite = bypassMemory
            });

        // For good measure
        await Task.Delay(200);

        // Ensure it's gone
        var record3 = await cache.GetOrDefaultAsync<PocoA?>(key,
            setupAction =>
            {
                setupAction.SkipMemoryCacheRead = bypassMemory;
                setupAction.SkipMemoryCacheWrite = bypassMemory;
            });

        // THIS FAILS
        Assert.That(record3, Is.Null);
    }

Expected behavior

Tagged cache entries in L2 cache are removed.

Versions

I've encountered this issue on:

  • FusionCache 2.1
  • .NET version 9

Additional context

I enable this automatically in order to test that deserialization works. I don't use this in production.

@jodydonetti
Copy link
Collaborator

Hi @sebbarg , when calling RemoveByTag("my-tag") tagged entries are not necessarily removed, and even if so, not directly when calling the method.

For more on the design decisions and the tradeoffs, take a look here.

Let me know if it makes sense, thanks.

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

No branches or pull requests

2 participants