It’s not a known issue with PooledRedisClientManager, but the sharing of Redis client could be happening anywhere you’re using Redis not just where the error occurred.
But I can see you’re re-registering TelemetryService in the IOC, please never ever do this, ServiceStack is responsible for registering and autowiring all Services, so remove the registration for TelemetryService and any other Services you’re doing this for.
Thanks for looking. I was hoping another set of eyes would reveal something obvious.
Turns out I was missing a ReuseScope when registering the RedisClientManagerCacheClient, so that should explain the problem.
container.Register<ICacheClient>(c => new RedisClientManagerCacheClient(c.Resolve<IRedisClientsManager>()));
Should be:
container.Register<ICacheClient>(c => new RedisClientManagerCacheClient(c.Resolve<IRedisClientsManager>()))
.ReusedWithin(ReuseScope.Request);
But I can see you’re re-registering TelemetryService in the IOC, please
never ever do this, ServiceStack is responsible for registering and
autowiring all Services, so remove the registration for TelemetryService
and any other Services you’re doing this for.
Thanks for the pointer, not sure why I was doing that.
That leaves me a bit stuck. Any ideas on how to find the cause?
All Redis usage in my entire app is via the auto-resolved Redis clients (via the Service.Redis property), so should be disposed and released back to the pool automatically when the request ends.
There are only 2 services that use Redis directly (outside of the ICacheClient usage). I’m not seeing anywhere the Redis clients could be leaking.
My logs have lots of RedisResponseExceptions with errors like:
Unknown reply on integer response: 43OK, LastCommand:'SADD…
Unknown reply on multi-request: 580, LastCommand:'ZRANGE…
From one of the bad keys in a Redis set, it seems that multiple instances of my TelemetryService are somehow sharing the same client:
“LastMessag$4\r\nEVAL\r\n$164\r\nlocal value = tonumber”
“LastMessageHandled” is what all the keys in the set should begin with.
“local value = tonumber” is the beginning of a Lua script that is called immediately after a key is added to the set: