Description
We have been experimenting with rueidis and noticing odd behaviour that doesn't seem to be captured by the test cases.
In some if our tests we're simply doing a set followed by a get immediately.
builder := rc.rueidisClient.B().Set().Key(key).Value(rueidis.BinaryString(b))
var built rueidis.Completed
// Not sure if this is needed, using the redis client is much easier for expirations.
if expiration >= time.Second {
built = builder.Ex(expiration).Build()
} else if expiration > 0 && expiration < time.Second {
built = builder.Px(expiration).Build()
} else {
built = builder.Build()
}
goErr := rc.rueidisClient.Do(ctx, built).Error()
// Then in another function immediately afterwards we try to get from the cache:
redisResult := rc.rueidisClient.DoCache(ctx, rc.rueidisClient.B().Get().Key(key).Cache(), ttl)
// Note: this scenario happens often and randomly where it says it's a local cache hit but
// it's a Nil error (ie. redis miss) and redisResults.AsBytes() is also empty.
// So we had to hack in falling back to making the redis call directly.
if redisResult.IsCacheHit() && redisResult.Error() == rueidis.Nil {
redisResult = rc.rueidisClient.Do(ctx, rc.rueidisClient.B().Get().Key(key).Build())
}
byteVal, goErr := redisResult.AsBytes()
So a few things are confusing us:
-
We find that IsCacheHit() and rueidis.Nil are both being returned from DoCache's result, which seems like a scenario that should never happen. To make tests more reliable we've had to fall back to calling redis (which we though DoCache was supposed to do for us). How is this happening?
-
Additionally, for test cases that have that Set() and Get() immediately afterwards to make them reliable I'm having to add a time.Sleep(time.Second) kind of pause, is that to be expected? When we have sleeps, the above scenario seems to happen less or not at all, but the above scenario shouldn't happen I would think ever regardless of sleeping.
-
Iin order to invalidate the local caches, does a Del() in rueidis do that or does only Set() do it? In trying to get tests to pass reliably it's not clear if we need a long sleep after Del() and Set() for the invalidation messages to propagate or if you need a Set() command in order to send the invalidation messages.
-
I looked through many tests cases in rueidis and they have Set() followed by Get() and have sensible hit and miss counters, but that doesn't seem to be the case when using it in practice so I'm wondering if the mocking in the tests is not representative.
-
Finally, it would be great to have examples to do simple stuff like above. The README is only showing a couple things and it took extensive amounts of time to look through the codebase to see the commands that are possible and how to use them.
Thanks for the help!