storage: add an in-memory implementation of CacheStorage
This serialises function arguments as a JSON string, casting values that
can't be serialised using `json.dumps` to a string. We add an additional
test case that such keys can be properly cached.