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