lonelyenvoy / python-memoization

A powerful caching library for Python, with TTL support and multiple algorithm options.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Feature request / Help wanted: Support for coroutines and async functions

TheClockTwister opened this issue · comments

Hi folks,
I really love your module and we even use it at work quit a lot :D
I wanted to contribute and add support for async methods but got stuck since I cannot really access the cache store behind the cached decorator...

here's the basic approach:

import asyncio
from time import perf_counter
from functools import wraps

def log(msg: str):
    print(f"[{round(perf_counter(),3)}]: {msg}")

class AsyncMemoize:
    def __init__(self) -> None:
        self.cache = {} # very silly store for proof of concept

    def __call__(self, function):
        @wraps(function)
        async def wrapped(*args):

            cache_key = hash(args) # 
            if self.cache.get(cache_key, ...) == ...:
                self.cache[cache_key] = await function(*args)
            return self.cache[cache_key]

        return wrapped

@AsyncMemoize()
async def calculate_stuff(n: int):
    await asyncio.sleep(1) # intensive calculation
    return n

async def main():
    log("Calculating...")
    await calculate_stuff(4)
    log("Calculating again...")
    await calculate_stuff(4)
    log("Calculating other...")
    await calculate_stuff(7)
    log("Calculating other again...")
    await calculate_stuff(7)
    log("All done!")

asyncio.run(main())

I could work with the cached decorator, however, this would mean making an async function call sync, and therefore blocking the thread, which is complete bullshit of cause 😆

If you can show me how to access the store directly, I'm gonna fork this repo and implement async support (which is really nice for things like server-side caching on Quart and FastAPI etc.) 😀

Best regards 👋