2

On the documentation it says

    /// The cache manager must have at least one cache handle configured with <see cref="CacheHandleConfiguration.IsBackplaneSource"/> set to <c>true</c>.
    /// Usually this is the redis cache handle, if configured. It should be the distributed and bottom most cache handle.

I know how to do it with RedisCacheHandle, since it's given as example on Cachemanager's website

var cache = CacheFactory.Build<int>("myCache", settings =>
{
    settings
    .WithSystemRuntimeCacheHandle("inProcessCache")
    .And
    .WithRedisConfiguration("redis", config =>
    {
        config.WithAllowAdmin()
            .WithDatabase(0)
            .WithEndpoint("localhost", 6379);
    })
    .WithMaxRetries(1000)
    .WithRetryTimeout(100)
    .WithRedisBackplane("redis")
    .WithRedisCacheHandle("redis", true);
});

The problem is I don't want to use Redis as cache resource; I just want to make a distributed cache by the power of Redis Pub/Sub mechanism. According to my debugging through the code, by using Redis Backplane feature I'm able to send messages to and receive messages from Redis indeed. So why not use RedisCacheHandle and instead use SystemRuntimeCacheHandle?

So, my expectation was the successfull execution with the following cache configuration

var cache = CacheFactory.Build<int>("myCache", settings =>
{
    settings
    .WithSystemRuntimeCacheHandle("inProcessCache")
    .And
    .WithRedisConfiguration("redis", config =>
    {
        config.WithAllowAdmin()
            .WithDatabase(0)
            .WithEndpoint("localhost", 6379);
    })
    .WithMaxRetries(1000)
    .WithRetryTimeout(100)
    .WithRedisBackplane("redis")
    .WithSystemRuntimeCacheHandle("inProcessCache", true);
});

But it's not working. Can you please show me a solution? What am I doing wrong? Or, eventhough it's written in the documentation as

...Usually this is the redis cache handle...

are there any way to use the cache synchronization feature without RedisCacheHandle?

https://github.com/MichaCo/CacheManager/issues/111

rebulanyum
  • 487
  • 10
  • 21

1 Answers1

0

I guess you with "nor working" you mean that the other caches do not get synced, e.g. if I delete a key from cacheA, it doesn't get deleted from cacheB? Yes this is currently an expected behavior.

The backplane is intended to work with out of process caches where you have only one state. With 2 instances of the cache both using system runtime caching, you have two totally disconnected in proc caches.

Normally, if you have a Redis layer and you remove a key from cache instance A, the item would be removed from the Redis layer. The message gets send to other instances of the same cache and would remove the key from any other cache layer but redis (the one marked as backplane source). This means, we expect that the backplane source is already in sync.

Now what if you have an in-process cache as backplane source. That doesn't work, because both instances will always be out of sync.

Lets look at this example:

var cacheConfig = ConfigurationBuilder.BuildConfiguration(settings =>
{
    settings
    .WithSystemRuntimeCacheHandle("inProcessCache")
    .And
    .WithRedisConfiguration("redis", config =>
    {
        config.WithAllowAdmin()
            .WithDatabase(0)
            .WithEndpoint("localhost", 6379);
    })
    .WithMaxRetries(1000)
    .WithRetryTimeout(100)
    .WithRedisBackplane("redis")
    .WithSystemRuntimeCacheHandle("inProcessCache", true);
});

var cacheA = new BaseCacheManager<string>(cacheConfig);
var cacheB = new BaseCacheManager<string>(cacheConfig);

cacheB.Backplane.Removed += (obj, args) =>
{
    Console.WriteLine(args.Key + " removed from B.");
};

cacheA.Add("key", "value");

var result = cacheB.Get("key");
Console.WriteLine("Result should be null:" + result);

cacheB.Add("key", "value");
result = cacheB.Get("key");
Console.WriteLine("Result should not be null:" + result);

// triggers backplane remove event
cacheA.Remove("key");

// lets give redis some time send messages
Thread.Sleep(100);

result = cacheB.Get("key");
Console.WriteLine("Result should be null again but isn't:" + result);

Console.ReadKey();

If you run this, you can see that the backplane event actually fires but because the only in-proc cache is the backplane source, the key does not get deleted. That's why at the end, you still get the key returned back to you.

As I said, that is currently the expected behavior.

You could implement custom logic with listening to those events though. (the events will change slightly in the next version, currently there are a few bugs and inconsistencies).

Also, don't expect that the backplane would transfer cache values over to other instances. That's not going to happen ever. CacheManager only sends key events, not the data because the data is handled by the out of process cache usually. Meaning, if you have in-proc cache only with backplane, adding an item in cacheA, will NOT copy the item to cacheB! You might get a change event for the key on cacheB though.

I hope that makes sense ;)

MichaC
  • 13,104
  • 2
  • 44
  • 56
  • I respect to your suggestion and posting my comments here rather than github. Actually the pattern forces me to use a "Cache Backplane Source". Well, that means this source is "The Source" of all others: meaning it's "The Master Source" among all other cache handles. This is why Redis Cache Handle works fine as a backplane source: because it's a single cache located at : address. On the other hand, MemoryCacheHandle can't handle this job. Why? It's because MemoryCacheHandle creates new MemoryCache everytime. Please check the MemoryCacheHandle class's constructer. – rebulanyum Nov 23 '16 at 04:31
  • So @michac, consider 2 MemoryCacheHandle each on a different computer. Can't they be synchronised by Redis pub/sub? One is master and the other is slave. That would be cool. And as an architecture it should be possible too. But it looks like your library doesn't support this way. – rebulanyum Nov 23 '16 at 04:38
  • That sounds more like a feature request to me now. Lets post this on gihtub with a link to this. I'm still not 100% sure what you acutally mean with sync? Actually copying new items or just removing ones which have been removed and such? Copy data and mimic a distributed cache is 100% not the way to go because that's why stuff like Redis exists ;) – MichaC Nov 23 '16 at 08:24