Cache management for RPC

Rational

Currently the tryton client has simple cache feature for some hard-coded method (fields_view_get, view_toolbar_get, get_keyword). This cache is invalidated by the logout.
Tryton could benefit from a more flexible cache system which could define what to cache and how long.
This cache could not reuse the standard HTTP feature because RPC requests are all POST method for which cache does not make sense.
So we need to define our own cache protocol which should defines which parameters of the requests must be used as key of cache.

Proposal

The RPC object will use to store cache configuration. It will store a timedelta for the cache duration and a list of context keys from which the request depends.
On the answer of a request with cache information, the server will add in the headers the context keys and the duration.
The client will store in a size limited dictionary the result of a request if the cache headers are available and the expiration date. It will construct the dictionary key using the arguments and the context keys converted into a hashable object (currently client uses str).
On the next request, the client will first construct the key an check it exists in the cache and if it is still valid. Then it will use the cached result if possible or it will make the request to the server.

The possible methods that could be cached by default are:

  • ModelView.fields_view_get
  • ModelView.view_toolbar_get
  • IrAction.get_keyword
  • Model.default_get
  • Model.fields_get

Some on_change_with could also benefit from this cache like the on_change_with_currency_digits's because they are often called with the same currency. But the client tries to group all the on_change* calls. So we will have to add on the fields definition that the on_change can be cached so the client will not group such query to benefit from the cache.

Implementation

https://bugs.tryton.org/issue8233
https://bugs.tryton.org/issue8234

Future

Some requests could push more result than the requested to pre-fill the cache with expected requests. But this will require to support HTTP/2.

1 Like

I do not think it will be possible to use HTTP header for that because in both client implementation the response header is not available easily and because the server architecture does not allow to set it at the same place as the RPC is defined.
We could neither return a custom data structure (like an extra key for JSON-RPC) because it will break the standard.
So indeed I think we could have a call like the system.listMethods which will return the list of all cache-able methods and their definition. This will be called at login. And it means the duration will be fixed for all the session.

Even without this more advanced cache management, it would be nice if we could disable cache for some rpc calls. Currently the tryton client caches the following RPC calls within a session:

  • fields_view_get()
  • view_toolbar_get()
  • ir.action.keyword’s get_keyword()

This improves performance a little bit but it also makes the system less flexible because does not allow developers to create dynamic views (overriding fields_view_get) in some circumstances.

Currently one can prevent that cache effect by ensuring the context is different each time the view needs to be reloaded from the server but it may be cleaner if the cached methods which currently already return a dictionary, checked if there’s a ‘cache=False’ key in it.

So as an example, fields_view_get doc would look like this:

@classmethod                                                                     
def fields_view_get(cls, view_id=None, view_type='form'):                        
    '''                                                                          
    Return a view definition.                                                    
    If view_id is None the first one will be used of view_type.                  
    The definition is a dictionary with keys:                                    
       - model: the model name                                                   
       - type: the type of the view                                              
       - view_id: the id of the view                                             
       - arch: the xml description of the view                                   
       - fields: a dictionary with the definition of each field in the view      
       - field_childs: the name of the childs field for tree
       - cache: boolean indicating if the client should cache the view (True, by default)                     

Thoughts?

1 Like

As usual, we do not do half solution. If we improve something we improve it in the good and generic way.

Having a special treatment for the context, force to guess to the JSON-RPC handler where the context is. I do not think it is a good practice.
Also it makes the extension of the RPC method more difficult because if a new context key is used, it must be declared.
So I think it is simpler and better to manage the context as a normal argument.

Here is the implementation Issue 8233: Add Cache management for RPC - Tryton issue tracker
The differences are:

  • No context keys but all context is used
  • No disabling of grouped on_change calls (will be done in later patch).

Implemented in Allow to cache on_change calls (#8234) · Issues · Tryton / Tryton · GitLab

This topic was automatically closed after 14 days. New replies are no longer allowed.