The default JHipster Caffeine configuration provide a too large time for the following parameter setExpireAfterWrite. L186.
It cause the cache to expire every after one hour after the last modification we did.
I think this is not the behaviour we are expected for.
If I compare the EHCache configuration L179, we set a timeToLiveExpiration parameter. According to the documentation
this means cache mappings will expire after a fixed duration following their creation
I think there is a misunderstanding between both way to configure Caffeine and EHCache configuration.
After a writing action we should refresh the cache as soon as possible, not after one hour :D.
Generate a project with Caffeine as cache. Update an entity. Wait for one hour (default JHipster value) to read the new value (ofc you should reduce the time-to-live value :D ).
Use setExpiryFactory instead of setExpireAfterWrite that should allow us to define a time between the last writing access has be done and when we want the cache to expire.
[email protected] /Users/aviard/projects/myproject
└── [email protected]
##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
{
"generator-jhipster": {
"promptValues": {
"packageName": "com.mycompany.fr",
"nativeLanguage": "fr"
},
"jhipsterVersion": "6.6.0",
"applicationType": "monolith",
"baseName": "myproject",
"packageName": "com.mycompany.fr",
"packageFolder": "com/mycompany/fr",
"serverPort": "8080",
"authenticationType": "jwt",
"cacheProvider": "caffeine",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "postgresql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSwaggerCodegen": true,
"jwtSecretKey": "itsecretsbro",
"embeddableLaunchScript": false,
"useSass": true,
"clientPackageManager": "npm",
"clientFramework": "angularX",
"clientTheme": "none",
"clientThemeVariant": "",
"creationTimestamp": 1578388948342,
"testFrameworks": [],
"jhiPrefix": "jhi",
"entitySuffix": "",
"dtoSuffix": "DTO",
"otherModules": [],
"enableTranslation": true,
"nativeLanguage": "fr",
"languages": ["fr", "en"],
"blueprints": []
}
}
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.6+10)
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.6+10, mixed mode)
git version 2.19.0
node: v12.16.1
npm: 6.13.4
yeoman: 2.0.5
yarn: 1.13.0
Docker version 19.03.4, build 9013bf5
docker-compose version 1.24.1, build 4667896b
entityName.json files generated in the .jhipster directoryhmm... I am a bit confused with this one. I think we had this discussion before. :thinking:
The documentation of Caffeine also seems to indicate that time-to-live expiration is expireAfterWrite :thinking:
cc: @ben-manes
There are two common variants of TTL in the wild:
(1) is common when the cache is read-through and the api disallows an explicit update call. For example when caching an external resource that one has no control over. This is could be implemented as (2), just not providing the api to do so (e.g. DNS).
(2) is how Caffeine / Guava implement expireAfterWrite, as local caches are often to data that they own (e.g. their database). Caffeine offers setting a custom expiration policy as well, so you can implement (1) if desired.
I suppose Ehcache went with (1), but even their wording is vague in v3 to be either implementation:
For instance the cache could be configured to expire entries five seconds after they are put into the cache - which is a time-to-live TTL setting. Or to expire entries 17 seconds after the last time the entry was retrieved from the cache - which is a time-to-idle TTI setting.
In v2 they are more accurately in defining TTL as expire after creation
timeToLiveSeconds – The maximum number of seconds an element can exist in the cache regardless of use. The element expires at this limit and will no longer be returned from Ehcache . The default value is 0, which means no TTL eviction takes place (infinite lifetime).
We decided on more explicit terms since it gets confusing when moving between systems that implement it differently. Its a term borrowed from networking for packets, and since one doesn't update a packet, the update behavior is undefined. I suppose you could try to reconcile it to whatever JHipster wants to define it and configure each cache provider accordingly.
Edit:
Oh right, this is JCache which is its own messiness. Their ExpiryPolicy would make sense to use.
After a full day of search, I can confirm that the Caffein cache configuration work as expected and the following ticket is no longer relevant.
It's a little confusing for me but I would like to thank you all for the informations you gave. The real problem was linked association table from a JDL specification and cache annotations on OneToMany associations. Nothing about Caffein, I was wrong.
have a nice day ;)
@ben-manes : Thanks much for your detailed explanation.
@avdev4j : Good to hear you figured it out. :+1:
Although I was wondering what we could do to avoid some confusion is to use default Caffeine terminology. That is instead of using time-to-live-seconds (in the application-prod.xml and application-dev.yml files) we could rename it to expire-after-write. WDYT?
adding docs or add a little comment in properties would be nice I think
Most helpful comment
There are two common variants of TTL in the wild:
(1) is common when the cache is read-through and the api disallows an explicit update call. For example when caching an external resource that one has no control over. This is could be implemented as (2), just not providing the api to do so (e.g. DNS).
(2) is how Caffeine / Guava implement
expireAfterWrite, as local caches are often to data that they own (e.g. their database). Caffeine offers setting a custom expiration policy as well, so you can implement (1) if desired.I suppose Ehcache went with (1), but even their wording is vague in v3 to be either implementation:
In v2 they are more accurately in defining TTL as expire after creation
We decided on more explicit terms since it gets confusing when moving between systems that implement it differently. Its a term borrowed from networking for packets, and since one doesn't update a packet, the update behavior is undefined. I suppose you could try to reconcile it to whatever JHipster wants to define it and configure each cache provider accordingly.
Edit:
Oh right, this is JCache which is its own messiness. Their
ExpiryPolicywould make sense to use.