Skip to content

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

Closed
@sebbarg

Description

@sebbarg

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions