Following my recent article on using Redis cache, I had a very interesting discussion with @tkvangorder as there is an interesting edge case: when you do a new release, you still inherit from the old cache, and maybe you will have some wrong data there, because you changed something in your code.
I think of it like a database: we use Liquibase to update the database, but what about the cache?
At first I thought we should have some specific task in our release process to clear out the cache, and I know many people who do that (including several of my own former clients!), but that's not a perfect solution, as you can't have a perfect system where the cache is cleared exactly at the same moment as the application is upgraded.
So @tkvangorder has a great solution: he's using the application version in the cache keys. This solves everything nicely!
With JHipster we could easily have something similar, as we have (at least with Maven) the Git commit id which is available as a Spring Boot property (${git.commit.id.describe}). So I wonder if we could have some specific Spring Cache implementation in JHipster Framework, where the default key would be automatically prefixed by that commit hash.
Just for reference, this repository, https://github.com/tkvangorder/redis-shared-cache-sample, provides an example of how the Spring Caching abstraction can be customized to support a "shared" distributed cache. The key is still cache-specific (like a customer ID), however, the values are a hash where the key in the hash is the application build number. It should be easy to adapt this such that the second key is git commit ID.
what about users which don't use git, but svn instead ?
Should git be as mandatory now ?
We could totally say that Git is mandatory... But for the moment we only check for it, and ignore the feature if it's not present: that could be the same here, this would only work if you use Git, and otherwise you wouldn't have the Git hash.
I think this should be optional. In some cases, even post upgrade, the cache can still hold valid data and need not be cleared. Also, using build/version number seems more generic as spring boot can provide that for both maven and gradle (assuming that it's not turned off)
The example is just pulling a property value from the Spring Environment. We could make this key configurable or look for well-known properties and just define order precedence (look for a git hash, if not there, look for a build number, etc). The only requirement is that this value is unique for each build. @vishal423 this enhancement would allow you to share your cache without clearing values even when the structure of the cached model has changed.
Is someone working in this and do we have a decision what to use as unique part of the cache key? Could work on this during hacktoberfest...
I've not had a lot of time lately to dedicate to open source, but I am more than happy to help anyone that wants to take on this issue. My DMs are open @tkvangorder on twitter.
Thanks @tkvangorder for the heads up! Will go on and propose a first PR.
Edit: @jdubois Did I get you right, that you had something in mind that generates a prefix for every cache key (and every cache implementation) via spring cache abstraction and not a specific redis or hazelcast solution?
@jdubois I have a small prototype with a custom spring cache key generator, that uses the git hash a the prefix for the cache key (derived from the default cache key generator). If there is no git hash it uses the build timestamp from the boot build information (or the version) and finally we could just use a random string as prefix or no prefix to have the current behavior.
I can do a PR if thats what you have in mind and we can discuss further as the additional code is not complex and quite small.
Thanks @atomfrede , yes it looks like what I have in mind. Could you do this in the framework in jhipster/jhipster so we don't generate this code, just use it?
Sure for the key generator itself. Configuration (~3-5 loc) must be generated in addition. Will push the sample today and do a first to jhipster lib.
Here is the sample repo (ignore the hibernate properties). The current implementaton behaves as the default SimpleCacheKey with an additional prefix. It could be even less code by doing (which also respects target and and methodname).
return prefix + target.getClass().getSimpleName() + "_"
+ method.getName() + "_"
+ StringUtils.arrayToDelimitedString(params, "_");
@atomfrede : I know you work on Neo4j support right now, but do you plan to achieve this ticket ?
Yes, I have a branch ready with the key generator for the server side library, so we can integrate it like in the sample repo with less generated code.
Most helpful comment
The example is just pulling a property value from the Spring Environment. We could make this key configurable or look for well-known properties and just define order precedence (look for a git hash, if not there, look for a build number, etc). The only requirement is that this value is unique for each build. @vishal423 this enhancement would allow you to share your cache without clearing values even when the structure of the cached model has changed.