Skip to content

Change cache to TLRU cache instead of a plain dict for noblock operations and ZMQ response message cache #120

@VigneshVSV

Description

@VigneshVSV

Please describe.

The client object can schedule an operation on the server with noblock=True and collect the reply later when its needed. For example:

msg_id = client.read_property("my_property", noblock=True)
# do many things
print("property value is :", client.read_reply(msg_id)) 

The above code snippet is possible for most operations on properties and actions with keyword argument noblock=True.

We use a plain dictionary to store:

  • the response cache in ZMQ protocol binding (core.zmq.brokers.BaseZMQClient)
  • the message map in core.zmq.brokers.MessageMappedClientPool
  • the noblock message IDs on the ObjectProxy (client.proxy.ObjectProxy)

all of which play a role in the noblock invokation. How it works:

  • an operation is scheduled on the server and a message ID is returned to the client
  • whenever a ZMQ client looks for a message from the server, if it does not receive a message for the current message ID its looking for, the response is still received but added to the cache.
  • whenever a response is asked again from the client, say for a different operation, it is checked whether the response is available in the cache before listening on the socket.
  • For noblock messages, if the response completed, the message would have usually arrived on the client and be added to the said cache. If not, it proceeds to look for it on the socket (with a timeout which is unfortunately currently disabled in v0.3 but was working in v0.2).

Replace all these caches with a TLRU cache so that the responses are automatically cleared after a certain period of time if the client never returns to ask for a noblock response. This is meant for conserving memory.

Use cases
This is a general pattern that I have used a lot in multi-client scenarios - an application that is connected to 100s for Things.
If you issued many noblock messages and for some reason not look for the response, the application memory consumption increases.

Describe the solution you'd like

Rough steps:

  • A TLRU cache based on a mapping is already implemented in cachetools, add it to pyproject.toml as a main dependency and import it in the specified files and replace the dictionary with this implementation.
  • Read the number of messages in the cache and the time to live from global_config object. Define two variables CACHE_TTL or CACHE_SIZE (or similar sounding words) and set default values to 2 hours and 10000 messages.
  • Add tests (docs for later). Use a small value of the TTL to make sure it works.
  • As an additional piece of refactoring work, make MessageMappedClientPool.message_map to reuse the _response_cache variable of BaseZMQClient. Its a duplicate and mostly not necessary. The tests test_05 and test_09 through test_12 must pass if this refactoring is correct. This piece of work is optional.

Additional context
For point 4 in "how it works" above, the timeout is not respected although accepted as an input parameter. Fix it if possible, its really important, if not, lets keep that later. There may be some information in the codebase for versions less than v0.3 on how it was working.

Metadata

Metadata

Assignees

No one assigned

    Labels

    good first issueGood for newcomersintermediateintermediate level good first issues, might be little harder to complete

    Type

    Projects

    Status

    Ready

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions