Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async versions of decorators? #137

Closed
pjz opened this issue Aug 17, 2019 · 2 comments
Closed

Async versions of decorators? #137

pjz opened this issue Aug 17, 2019 · 2 comments

Comments

@pjz
Copy link

pjz commented Aug 17, 2019

For fluency I really like the decorator-style caching, but they don't work when used to decorate async functions - which, I think, are functions you'd frequently want to cache because they're often used when doing I/O.

@pjz
Copy link
Author

pjz commented Aug 17, 2019

Here's an async-compatible version of the cachetools.cached decorator, for instance:

def cached(cache, key=cachetools.keys.hashkey, lock=None):                                                             
    """                                                                                                                
    Decorator to wrap an async function with a memoizing callable that saves results in a cache.                       
    """                                                                                                                
    def decorator(func):                                                                                               
        if cache is None:                                                                                              
            async def wrapper(*args, **kwargs):                                                                        
                return await func(*args, **kwargs)                                                                           
        elif lock is None:                                                                                             
            async def wrapper(*args, **kwargs):                                                                        
                k = key(*args, **kwargs)                                                                               
                try:                                                                                                   
                    return cache[k]                                                                                    
                except KeyError:                                                                                       
                    pass  # key not found                                                                              
                v = await func(*args, **kwargs)                                                                        
                try:                                                                                                   
                    cache[k] = v                                                                                       
                except ValueError:                                                                                     
                    pass  # value too large                                                                            
                return v                                                                                               
        else:                                                                                                          
            async def wrapper(*args, **kwargs):                                                                        
                k = key(*args, **kwargs)                                                                               
                try:                                                                                                   
                    with lock:                                                                                         
                        return cache[k]                                                                                
                except KeyError:                                                                                       
                    pass  # key not found                                                                              
                v = await func(*args, **kwargs)                                                                        
                try:                                                                                                   
                    with lock:                                                                                         
                        cache[k] = v                                                                                   
                except ValueError:                                                                                     
                    pass  # value too large                                                                            
                return v                                                                                               
        return update_wrapper(wrapper, func)                                                                           
    return decorator    

@tkem
Copy link
Owner

tkem commented Aug 19, 2019

Please have a look at #92, #112 and https://github.com/hephex/asyncache.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants