philippgille/gokv

Expiration by time

tdakkota opened this issue · 2 comments

some KV stores like Redis and Memcached can automaticly remove expired keys, but gokv can't

I saw the first item of Design decisions, but i think that gokv can provide multiple interfaces, like gokv.Cache

Hi @tdakkota, thanks for the feature request!

You're right that another interface could be added to the root gokv package and that wouldn't have any negative consequences to packages using gokv.Store so far (like added dependencies or so).

Regarding the implementations it's a little bit more difficult: Redis and Memcached have native support for key-value pair expiration, but other products that have implementations for gokv.Store already don't have this.

There are some ways to implement that on your own:

  • Each xyz.Set("key", "val", expiration) call could lead to a goroutine with a timer that calls xyz.Delete("key") after the expiration, but that wouldn't work as soon as the program crashes or something
  • When xyz.Set is called, it could add its own metadata in addition to the value, with the metadata including the expiration date. A xyz.Get call would lead to gokv checking the expiration in the metadata, deleting the value if the expiration is reached, or otherwise return the actual value. This would lead to the package behaving like a cache, but the cache might actually grow very big due to stale entries that are just not deleted because no xyz.Get was called on them yet.
    • This could be mitigated by a goroutine that runs in the background every now and then to go through all key-value pairs, check their expiration and remove the expired ones. This requires a way to retrieve all key-value pairs though and I'm not sure if all products that have implementations for gokv.Store support this. (It's the same issue for #9).
  • Maybe other ways?

An alternative would be to only support the products that contain an expiration mechanism on their own, like Redis and Memcached. That might lead to confusion by people who use gokv.Store and think something like "when I use this gokv interface I know my package users who use product xyz can use it" and presume the same goes for the cache interface. Although maybe this could be mitigated with good documentation. For example the README could contain a table (instead of the current Implementations list) with the interfaces as columns and the products as rows, like:

Package gokv.Store gokv.Cache
redis ✔️ ✔️
file ✔️

Which would you prefer? (Only support the products with expiration support vs. implementing cache entry deletion on our own for products without expiration support)