Muhammad Makhaly
Muhammad Makhaly

Reputation: 51

Using Redis Pub/Sub to Invalidate Memory Cache using ChangeMonitor

I have created a new class that will be used to invalidate the Memory Cached data and load new Copy of the data from Redis. Also it depends on the pub/sub feature of Redis.

public class RedisChangeMonitor : ChangeMonitor
{
    private string uniqueId;
    private ISubscriber subscriber;

    private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
    {
        ConnectionMultiplexer connectionMultiplexer = ConnectionMultiplexer.Connect(ConfigurationManager.ConnectionStrings["RedisConnectionString"].ConnectionString);
        connectionMultiplexer.PreserveAsyncOrder = false;
        return connectionMultiplexer;
    });

    public ConnectionMultiplexer Connection
    {
        get
        {
            return lazyConnection.Value;
        }
    }

    public override string UniqueId
    {
        get
        {
            return uniqueId;
        }
    }

    public RedisChangeMonitor(IList<string> cacheKeys)
    {
        bool isInitialized = false;
        try
        {
            this.uniqueId = Guid.NewGuid().ToString();

            subscriber = this.Connection.GetSubscriber();
            subscriber.Subscribe(RedisChannels.ChangeNotification, (channel, data) =>
            {
                string cacheKey = data;
                if (cacheKeys.Contains(cacheKey))
                {
                    base.OnChanged(null);
                }
            });
            isInitialized = true;
        }
        finally
        {
            base.InitializationComplete();
            if (!isInitialized)
                Dispose(true);
        }
    }

    ~RedisChangeMonitor()
    {
        Dispose(false);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (subscriber != null)
            {
                subscriber.Unsubscribe(RedisChannels.ChangeNotification);
            }
        }
    }
}

I used this class in ASP.NET MVC App, i have seen that the memory of the server is full after around 1 hour if i didn't unsubscribe in the dispose method.

If i have unsubscribed in the Dispose method, the memory status is ok. But the Memory Cache is not invalidated.

Upvotes: 1

Views: 971

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062492

It looks like you're subscribing per instance, but your usage of unsubscribe currently doesn't pass in a delegate, and is therefore "unsubscribe everyone".

You should move the lambda to a local method and pass a compatible delegate to both subscribe and unsubscribe.

Upvotes: 0

Related Questions