Grails/Hibernate Cache unpredictable

Donald Jackson

I only resort to StackOverflow when I've really tried everything but I just cannot figure out how to solve this problem. It is quite easy to replicate, basically I have a table (basically just a key/value table where I keep settings).

class SystemSetting {
    Group settingGroup
    String key
    String value
    String label
    String type

    Date lastUpdated
    Date dateCreated
}

I have a simple controller which allows me to update these settings (@Transactional annotation) and 'flush: true' on the save.

Now, lets say I set an option from true to false (or any change) once this change is made, it is not reflected on other processes/sessions.

The code to read a setting is the following:

SystemSetting setting = SystemSetting.find("FROM SystemSetting ss WHERE ss.settingGroup = :group AND ss.key = :key",
            [group: group, key: key]
        );

So for example, in browser A) I update a setting. In browser B (or curl) when I view/access this setting it still has the old value.

I have disabled all the caching I know of:

hibernate {
    cache.use_second_level_cache = false
    cache.use_query_cache = false
    cache.region.factory_class = 'org.hibernate.cache.ehcache.EhCacheRegionFactory' // Hibernate 4
    singleSession = true // configure OSIV singleSession mode
    flush.mode = 'manual' // OSIV session flush mode outside of transactional context
}

grails.hibernate.cache.queries = false

But these results are still easily duplicated. What/why/where is this option being cached and how to I invalidate it?

This is really not leaving me with a warm feeling inside as it creates tons of issues if I can't be confident of what data will be coming out of the database :(

Using Grails 2.5.1 (and tested on 2.4.4, same result).

UPDATE:

I have been able to duplicate this in a fresh application.

Application is available here: https://github.com/donald-jackson/grails-async-error-demo

To duplicate:

  1. Clone the repository and configure the datasource to use your local MySQL.
  2. 'run-app' in Grails and visit /AsyncErrorTest/systemSetting
  3. Create a setting with optionName = 'testOption' set value to true (or false)
  4. Using curl (or other browser) visit /AsyncErrorTest/systemSetting/showVariable a few times, change the variable value and you will see the output correctly reflects the changes.
  5. Change the value of 'testOption' again.
  6. Call /AsyncErrorTest/systemSetting/showVariableAsync a few times using curl and you will notice the variable will start changing its value between the current and previous.
  7. Once you notice this behaviour you can check in your browser or even on the original showVariable method and it will also give unreliable output.
Donald Jackson

This was reported to Grails issues and was fixed in Grails 2.5.2.

https://github.com/grails/grails-core/issues/9198

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related