blueprinter icon indicating copy to clipboard operation
blueprinter copied to clipboard

WIP: Add caching support

Open Varek opened this issue 4 years ago • 2 comments

This PR will add framework agnostic caching support. I took inspiration from the latest cache implementation of jsonapi-serializer a fork from the Netflix's fast_jsonapi.

How it works

class UserBlueprint < Blueprinter::Base
  cache store: ActiveSupport::Cache::MemoryStore.new, ##Or: Rails.cache
        expires_in: 10.minutes

  identifier :uuid

  fields :first_name, :last_name, :email
end

To enable caching you just need specify a store, everything goes as long as it implements a fetch method.

Open Questions

I verified that it works in general works, but it needs some fine tuning. Some bigger questions I still have:

1) How far do we want to go with the cache key and busting of caches

I tried to go relatively deep to build a good bustable cache key, but I'm unsure if it's worth the effort. I was trying to go down to the extractors, so that we can invalidate the cache when fields on an association change. With the current structure of the association extractor it feels not easily done. What do you think? For context, as far as I can see the jsonapi-serializer is not doing anything to bust caches when serializers change.

2) Caching of associations

I my current implementation all fields including the associations are cached. Which currently means if the associated blueprint is also configured to be cached, it would be cached twice. Should we do one or the other, should it be configurable?

3) Configurable caching on field level vs. caching transformers

At the moment I cache also the transformer outputs. But if we make caching of fields/associations configurable this doesn't make much sense anymore. I'm unsure if caching transformers at all makes sense. As I didn't had any real world use case for using them, I can't really gauge the impact in either direction. What are you thinking? Also should we be able to define caching behaviour on field level in the first place?

Hope you like the general approach, and happy to hear your input on this.

Varek avatar Apr 12 '21 17:04 Varek

This would be a great addition!

scarroll32 avatar Apr 27 '21 11:04 scarroll32

It would be extremely great to have this in Blueprinter!

IMO the crucial thing to make this useful is for it to behave like regular Rails views and as such, we need to find equivalents for the concepts used there:

  • The main blueprint (the one that's actually explicitly rendered), more specifically, the name of the blueprint class + view inside (default if not explicitly given) is basically an equivalent of a view.
  • Any nested blueprints (a.k.a. associations) are the equivalent of partials.

The approach that Rails takes, as you might know, is to take into account 1) the rendered model's class name, 2) the model's updated_at timestamp and 3) the digest of view (including its dependencies). So any meaningful caching approach needs to take a similar approach, so that caching and especially automatic expiration works as expected (e.g. when a main blueprint has 4 associated objects and one of them gets updated, that object's cache + the main blueprint's cache get expired, but not that of the 3 other unmodified objects).

I would imagine that it would be possible to either use ActionView::Digestor and ActionView::DependencyTracker directly or at least use it as a strong inspiration, because the concepts behind it are sound.

clemens avatar May 18 '22 08:05 clemens

Hello @Varek , while i using this i got an error " undefined method `cache' " Can u pls help me to find this?

class Api::V1::UserBlueprint < Blueprinter::Base cache store: ActiveSupport::Cache::RedisCacheStore.new, ##Or: Rails.cache expires_in: 10.minutes

identifier :uuid

fields :first_name, :last_name, :email end

umamaheswari-raj avatar Jul 28 '23 08:07 umamaheswari-raj

This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

github-actions[bot] avatar Nov 05 '23 01:11 github-actions[bot]