simple-memory-cache

Dead Simple Memory Cache


Install
pip install simple-memory-cache==1.0.0

Documentation

Simple Memory Cache

A dead simple memory cache to allow a variable to easily be lazy-loaded when needed. Only 43 lines of code and no dependencies.

This module is used by our SpinHub App (https://www.spinhub.ca) which is currently in development. It allows us to in-memory cache variables for re-use in successful AWS Lambda function executions.

Use-case 1: Caching responses

A specific use case for us is to cache de JWKS (the JSON Web Key Set) of our Auth0 domain:


import requests
from simple_memory_cache import GLOBAL_CACHE

AUTH0_DOMAIN = 'mysubdomain.auth0.com'

JWKS_URL = AUTH0_DOMAIN + '/.well-known/jwks.json'

jwks_var = GLOBAL_CACHE.MemoryCachedVar('jwks')

@jwks.on_first_access
def _retrieve_jwks():
    return requests.get(JWKS_URL).json()

def do_something():

    # First call will trigger _retrieve_jwks and store the return value.
    # If this is called within the same AWS Lambda instance, the global context will still be there
    # and the value will simply be returned
    jwks = jwks_var.get() 

    try:
        (validate JWT token w/ jwks)
    except (ValidationError):
        # On a validation error, Auth0 recommends to refetch the JWKS in case it changed.
        # We invalidate the value and get it once again.
        jwks_var.invalidate()
        jwks = jwks_var.get()
        (validate JWT token w/ jwks)

Use-case 2: Specific Implementation for Flask Globals

We often encounter the case where we wish to set a Flask g member only if it is not set. You can create your own MemoryCachedVar adapted to this case in 5 lines of code:


from simple_memory_cache import CachedVar, NO_VALUE_STORED

from flask import g, request

class FlaskGCache(CachedVar):
    def _get_stored_value(self):
        return getattr(g, self.name, NO_VALUE_STORED)
    
    def _set_stored_value(self, value):
        setattr(g, self.name, value)   
        

app = (...)

user_var = FlaskGCache('user')

@user_var.on_first_access
def retrieve_user_from_request():
    token = request.headers.get('Authorization', None)
    # ... Decode token or raise Unauthorized
    return user

@app.route()
def private_route():
    user = user_var.get() # Authorizes the user once, will raise Unauthorized if unable.
    # ...
    user = user_var.get() # Simply returns the value stored in g.user
    

Creators

Created by Tack Verification, a company dedicated to reducing operational costs related to hardware systems verification. https://www.tackv.ca