Generator-jhipster: Caffeine cache has a too large time of expire after writing into

Created on 10 Mar 2020  Â·  5Comments  Â·  Source: jhipster/generator-jhipster

Overview of the issue

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.

Motivation for or Use Case

After a writing action we should refresh the cache as soon as possible, not after one hour :D.

Reproduce the error

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 ).

Related issues

Suggest a Fix

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.

JHipster Version(s)
[email protected] /Users/aviard/projects/myproject
└── [email protected] 

##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
.yo-rc.json file
{
  "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": []
  }
}

Environment and Tools

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

Entity configuration(s) entityName.json files generated in the .jhipster directory

Browsers and Operating System

  • [x] Checking this box is mandatory (this is just to show you read everything)

area caffeine

Most helpful comment

There are two common variants of TTL in the wild:

  1. Time after creation
  2. Time after create or last update

(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.

All 5 comments

hmm... 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. Time after creation
  2. Time after create or last update

(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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chegola picture chegola  Â·  4Comments

tomj0101 picture tomj0101  Â·  3Comments

ahmedeldeeb25 picture ahmedeldeeb25  Â·  3Comments

edvjacek picture edvjacek  Â·  3Comments

RizziCR picture RizziCR  Â·  3Comments