Giter Club home page Giter Club logo

aiocache's People

Contributors

abusi avatar ahopkins avatar argaen avatar arvind2222 avatar asvetlov avatar aviv-ebates avatar bbelyeu avatar ben-cutler-datarobot avatar daroee avatar dependabot[bot] avatar dmtr avatar dreamsorcerer avatar fogapod avatar haizhou avatar havardthom avatar jairhenrique avatar jayvdb avatar jcugat avatar jeppeklitgaard avatar jsoucheiron avatar jwshields avatar kevinmarsh avatar mark90 avatar masipcat avatar mgorny avatar minhtule avatar mmamkin avatar nkoshell avatar padraic-shafer avatar pyup-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aiocache's Issues

Improve testing for multi_cached

Lot of bugs found, need to improve testing with the keys_attribute thing

Wasnt bugs at all but feature. Should rethink about its behavior:

  • We want to call the function if no keys are passed? Should it work without keys? Maybe not...

Performance test suit

Its time to start adding some checks to the operations (without taking into account latencies with external storages) since caching should be as transparent as posible for the users.

Track keys by namespace in the storage

Some operations need to have knowledge of the keys stored in the storage. LRUPolicy is tracking the keys in memory but this is wrong because the state is lost when the process exits.

Should modify the behavior so the operations that change db status keep a list of the existing keys also in the same storage

Add clear cache operation

All backends must support cleaning the cache.

This is not as easy at seems, should every instance keep a list of keys that has added so it removes only those? Should it work by namespace? What if another key starts by that namespace unintentionally? we would remove that and it's wrong... Is it time to start using different databases for each namespace (check how to do that with memcached)?

Use examples as acceptance

Examples are a good way to cover use cases, lets use them as acceptance. To do so we need:

  • Add asserts to check correct calls
  • Add cleanups after execution
  • Make pytest run them

Try mixins strategy for backends

Once the refactor is done, backends will be just simple wrappers for connecting with the underlying clients like aioredis, aiomcached, dict, etc.

Try to think of a mixins approach in order be able to call the client commands as if you were using it straightforward.

Decorator with mset/mget behavior

Now that mget, mset support has been added. A decorator for setting/retrieving multiple keys can be implemented.

The decorator should be able to retrieve the available keys and just query for the missing ones.

Make policy to be the hook mechanism

Policies should be transformed to Hook mechanism, this way the user can implement whatever behavior he wants. The naming will change so it will introduce a breaking change. Also, in order for the user to implement interesting actions, some data the hooks should receive is:

  • key
  • value
  • time of execution (only post)
  • CMD executed

TODO:

  • Rename Policy to a name that indicates more generic behavior like Plugin, Hook or so. Remember to update docs
  • Document well that the user can use this to implement whatever policy/behavior they would like BUT they should be careful with consistency/race conditions when executing this from multiple clients (if they are interacting with the storage).
  • Remove the LRUPolicy and leave only the Default one. LRUPolicy can be an example of custom Plugin (say there that there can be inconsistency problems if different instances are using the same).
  • All operations must have a pre and a post hook that are always executed (user will decide wether to use and execute htem or not).

`cached` decorator creates new backend per decorated function

def cached(cache=None,...):
    cache = get_cache(cache=cache, ...)
    # ...
    def cached_decorator(fn):
        # ...
    return cached_decorator

Basically, get_cache returns new instance of backend for every call.
This mean that every decorated function will have its own instance of backend
and that every such function will create at least one connection to some
remote resource (redis, memcached, etc) (only if its not MemoryBackend)
and this might become a problem.

Refactor using main Cache class

Using RedisCache, SimpleMemoryCache and company as user classes, we are facing some design problems like reusing code, making serializer aware of the backend being used is difficult, etc.

A new design will be done were a main Cache class will be used. This class will contain the three main components:

  • Backend
  • Serializer
  • Policy

The class will expose the interface to interact with the cache and wrap the backend calls with the serializer and policy calls.

Use encoding from the serializer if specified

There is an encoding attr defined for serializer because in some cases it is needed for aioredis. To keep the interface clean, the encoding part should be done in the serializer layer. This will help also in the case of memcached implementation

Instructions for contributors

Add instructions for contributors. Before that, tests should be able to be run with docker env (needing to install redis and memcached for running them sucks).

A file for CHANGES should also be added for keeping track together with CONTRIBUTORS file.

Implement a way to list which serializer for each backend

Some serializers may not be compatible with a given backend. This error would be better if its raised during instantiation time rather than when calling the actual operations. The error should also return which serializers are supported.

Improve behavior of default config

if a namespace is passed, it should create a new instance of the default config but with the new namespace. Things to do:

  • Use either classes or instances for serializers and policies.
  • Check whether SimpleMemoryBackend can accept extra args/kwargs.
  • set_defaults should use strings, this way other classes from different modules can be used without causing cyclic imports and other problems.
  • Reuse backends (connections) if there is already an existing one. -> The create_pool should be outside, maybe a post_init for backends? ...
  • Improve settings module to pass args to the backend and the policy

multi_cached more flexible

Right now it only works with functions returning dicts and knows the keys if a param called keys is passed. Some modifications to improve its flexibility:

  • Param to the decorator to choose which param is receiving the keys.
  • Check how to make it work when returning pairs.
  • also cached decorator can be modified to support which attribute wants to be used as a key.

Implement locking to avoid dogpile effects

This would help to avoid problems like race conditions, dogpile effect, etc.

Some ideas:

References:

Couple of things to keep in mind:

  • Keep this as decoupled as possible, I don't know yet all use cases but for consistency, the approaches described below are not the most recommended. Since the main use case now is avoid stampede and avoid race conditions, we are "fine".
  • Should add disclaimers that the lock doesn't aim for consistency.

Redis

For now I'm thinking about going for using the simple approach described in https://redis.io/topics/distlock#correct-implementation-with-a-single-instance (lease time should be able to be passed by the user).

Memcached

https://bluxte.net/musings/2009/10/28/simple-distributed-lock-memcached/
https://github.com/memcached/memcached/wiki/ProgrammingTricks#avoiding-stampeding-herd

Memory

Just go with asyncio.Lock

Add max keys when configuring the backend

The option should be compatible with the decorator too. Lets put a simple case:

Imagine we want to store a maximum number of keys for each different function call. By specifying a max per backend, we may end up doing lots of cache misses because we are deleting keys from other functions.

There isn't much problem in general because each decorator instantiates its own instance of the backend. The only edge case is when using the config_default_cache where the developer may put a small size for the keys and then use it for multiple function calls. Maybe a warning could be displayed if the developer is configuring the cache with the max_keys option.

Challenges:

  • How to remove oldest key for each backend. To keep it simple, right now it won't be persistent. Each backend will keep a list of keys to track which has to be removed. This raises a "problem" with distributed systems like Redis: The number of keys won't be for the storage but for each backend/machine... Is this the behavior expected?
  • Deal correctly with max_keys per backend/decorator: Should propagate the arg to the init of the backend instance

Make tests suite more maintainable

Most of the methods for each backend are doing the same. Try to just use one test file and passing the tests for each backend available.

Also Redis and Memcached should run in containers when launching the tests.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.