Search code examples
objectify

Session cache in Objectify is not updated for update of the entity. It returns only the stale data


I am working on a we Maven Multimodule project in google appengine. There are 3 modules. default, backend and api. backend and api are the modules that uses objectify to store data and default contains the front end code. All the web related requests from default module are handled by backend module and works perfectly. But the api module is where I am facing the issue. Some data is pushed from external apps through the api and is being saved or updated in this app using Objectify. When I try to fetch the same to show it on the page details section after, the stale data (un updated data) is being returned. I don't face this issue, when the request is through UI.

Note : 1. I configured ObjectifyFilter in web.xml for both backend and api modules. I believe, this does the cleanup work upon updates/ save. It is configured for all endpoints in the app. (/*)

  1. This occurs only after the update for this Entity. All the Entities are Registered.

  2. Using ofy.clear() before load() works well. I believe this clears the session cache.

  3. No Problem with the Filter orders (there is one extra Auth filter in addition to Objectify Filter.) . ObjectifyFilter takes priority as I configured above the AuthFilter.

  4. I was using basic-scaling, but later on removed it by seeing a github thread on the Objectifyfilter topic, but no luck in solving this.

  5. Similar issue popped up in one more place, But I handled it as separate task queue as it is a dependent task (triggered when another entity is saved / updated). But this is a unitary operation.

The fetch code that i use right now is

log.info("DAO :: fetch()");
        if(ofy.isLoaded(Key.create(Class.forName(className),key))) {
            log.info("session cache is loaded and key is present in it.");
            ofy.clear();
        }else {
            log.info("session cache is not loaded and key is not present in it. ==========> ofy.clear()");
        }
        entity = (DAO) ofy.load().type(Class.forName(className)).id(key).now();

Solution

  • The session cache always returns the present content of the session. You need to be aware of the scope of the session while working - if you're using the ObjectifyFilter, by default you have a session cache for one single request. You can create new session scopes by running ObjectifyService.run() or starting transactions. Sessions are single-threaded, only relevant to a single thread of execution, and should be short-lived.

    If you're trying to get multiple processes or threads of execution to interact with common data in a meaningful way, you probably want transactions. Transactions are the only way to guarantee a consistent view of data in the datastore - even without a session cache, data is stale the moment you read it (someone else could have changed it one nanosecond later). Transactions solve this problem.