rfink / sequelize-redis-cache

Small fluent interface for caching sequelize database query results in redis more easily
MIT License
174 stars 47 forks source link

Cache policies and cache invalidation #21

Closed roccomuso closed 7 years ago

roccomuso commented 8 years ago

I would reccommend to edit the README.md to insert some hints on how to choose the best TTL value according to the application type :)

Moreover, we should think about a cache invalidation mechanism :) any hints?

mturner commented 8 years ago

This library could have a lot of potential, the invalidation of an object is definitely a big need.

rfink commented 8 years ago

I really like the idea, but there are complications of that, which I haven't quite figured out how to handle elegantly. Example: let's say you have a "User" record, and you cache that particular record. If we plugged into sequelize, we could easily invalidate that record on save/update. But what if you then cache a collection of users based on a SQL query? For example, all users in a specific timezone. How would we invalidate that collection? Currently we use an md5 hash of the query as the redis key, so we can't practically inspect every single cache item in redis. Those are the issue I wrestle with, in considering expanding the functionality beyond a simple caching layer.

rfink commented 7 years ago

I've added a link to Amazon's caching strategies / recommendations to the README.md. I'm going to close this issue, but I'm still open to any ideas on making this more robust, in terms of cache management.

Naoto-Ida commented 7 years ago

I +1 this addition. @rfink, when you're talking about users and timezones, are you referring to a situation like this?:

  1. Get a collection of users (id 1 through id 5) that have their timezone set to JST
  2. User with id 2 changes settings to PST, resulting in resetting cache for User with id 2
  3. Cache for collection of users mentioned in no.1 should be invalidated

I'm using this library with GraphQL, where I need cache invalidation for mutations(create/update/delete), i.e. user presses like button on an article, API records that like by the user, then the API needs to return the article data with the updated like count after invalidating the cached data for that article.

rfink commented 7 years ago

@Naoto-Ida - yes that is a great example of the situation that is difficult to handle programmatically. Especially now with the new raw query capabilities.

gijo-varghese commented 6 years ago

@rfink its a really good library. However, without cache invalidation methods, we can't use it

rfink commented 6 years ago

Thank you for enjoying it. I'm open to suggestions on how to implement cache invalidation on a larger scale, but we haven't been able to come up with anything quite yet.

gijo-varghese commented 6 years ago

@rfink there are lifecycle hooks for create and update right? Why can't we clear the cache on these hooks? Next time a find* is done, insert it back to cache.

rfink commented 6 years ago

So that's an idea that's been thrown around, and definitely possible, but that wouldn't include ranged or complex queries that include those records, such as .findAll({ where: { date: { $gt: 2017-01-01T00:00:00Z' } } });

So the behavior would be inconsistent. What are your thoughts on that?

gijo-varghese commented 6 years ago

did you mean update instead of find? like model.update(args, { where: { date: { $gt: 2017-01-01T00:00:00Z' } } });

gijo-varghese commented 6 years ago

oh, when findAll({ where: { date: { $gt: 2017-01-01T00:00:00Z' } } }); is executed a cache is built with its hash right?

rfink commented 6 years ago

Right - which we wouldn't be able to determine all possible objects that were affected. That's been my biggest concern with the cache busting.

rfink commented 6 years ago

Maybe the behavior is opt in, with good documentation on what wouldn't be invalidated properly. I know this is a large issue for some, and I'd love to find a way to tackle it.

gijo-varghese commented 6 years ago

hmmm. Let me do a research about in detail. I'll get back to you in a few days

rfink commented 6 years ago

Great, thanks! I'm looking forward to what you find.

gijo-varghese commented 6 years ago

@rfink How's the data of cached queries currently stored in Redis? A hash of the query and its result?

rfink commented 6 years ago

Right, the key is an MD5 hash of the JSON query object passed in the findX call, and the value is the raw JSON string of the results.

gijo-varghese commented 6 years ago

ok