-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ensuring read_multi works with fragment cache. #1814
Changes from 3 commits
11142e9
b295ce4
536dabb
decf414
aa85b5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -197,7 +197,7 @@ def object_cache_keys(collection_serializer, adapter_instance, include_directive | |
def object_cache_key(serializer, adapter_instance) | ||
return unless serializer.present? && serializer.object.present? | ||
|
||
serializer.class.cache_enabled? ? serializer.cache_key(adapter_instance) : nil | ||
(serializer.class.cache_enabled? || serializer.class.fragment_cache_enabled?) ? serializer.cache_key(adapter_instance) : nil | ||
end | ||
end | ||
|
||
|
@@ -211,7 +211,7 @@ def fetch_attributes(fields, cached_attributes, adapter_instance) | |
end | ||
end | ||
elsif serializer_class.fragment_cache_enabled? | ||
fetch_attributes_fragment(adapter_instance) | ||
fetch_attributes_fragment(adapter_instance, cached_attributes) | ||
else | ||
attributes(fields, true) | ||
end | ||
|
@@ -227,28 +227,34 @@ def fetch(adapter_instance, cache_options = serializer_class._cache_options) | |
end | ||
end | ||
|
||
def non_cached_attributes(adapter_instance, fields) | ||
non_cached_fields = fields[:non_cached].dup | ||
non_cached_hash = attributes(non_cached_fields, true) | ||
include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys) | ||
non_cached_hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) | ||
non_cached_hash | ||
end | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this looks like it was removed from Also, when adding methods, since this is in such flux, please prepend with comment There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rbocop thing. I would rather not change what it was, but it kept complaining about code complexity (the nested fetches). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh, so just |
||
# 1. Determine cached fields from serializer class options | ||
# 2. Get non_cached_fields and fetch cache_fields | ||
# 3. Merge the two hashes using adapter_instance#fragment_cache | ||
def fetch_attributes_fragment(adapter_instance) | ||
def fetch_attributes_fragment(adapter_instance, cached_attributes = {}) | ||
serializer_class._cache_options ||= {} | ||
serializer_class._cache_options[:key] = serializer_class._cache_key if serializer_class._cache_key | ||
fields = serializer_class.fragmented_attributes | ||
|
||
non_cached_fields = fields[:non_cached].dup | ||
non_cached_hash = attributes(non_cached_fields, true) | ||
include_directive = JSONAPI::IncludeDirective.new(non_cached_fields - non_cached_hash.keys) | ||
non_cached_hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) | ||
non_cached_hash = non_cached_attributes(adapter_instance, fields) | ||
|
||
cached_fields = fields[:cached].dup | ||
key = cache_key(adapter_instance) | ||
cached_hash = | ||
serializer_class.cache_store.fetch(key, serializer_class._cache_options) do | ||
hash = attributes(cached_fields, true) | ||
include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys) | ||
hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) | ||
cached_attributes.fetch(key) do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is pretty much the line that makes it work for fragments. Is there something I am missing here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah, brain 💨. was thinking in terms of the cache_store.fetch below, not that cached_attributes.fetch fires first in cache we read_multi already got it |
||
serializer_class.cache_store.fetch(key, serializer_class._cache_options) do | ||
hash = attributes(cached_fields, true) | ||
include_directive = JSONAPI::IncludeDirective.new(cached_fields - hash.keys) | ||
hash.merge! resource_relationships({}, { include_directive: include_directive }, adapter_instance) | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💯 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder whether we could use MSET as well. |
||
end | ||
|
||
# Merge both results | ||
adapter_instance.fragment_cache(cached_hash, non_cached_hash) | ||
end | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -321,6 +321,36 @@ def test_fetch_attributes_from_cache | |
end | ||
end | ||
|
||
def test_cache_read_multi_with_fragment_cache_enabled | ||
post_serializer = Class.new(ActiveModel::Serializer) do | ||
cache except: [:body] | ||
end | ||
|
||
serializers = ActiveModel::Serializer::CollectionSerializer.new([@post, @post], serializer: post_serializer) | ||
|
||
Timecop.freeze(Time.current) do | ||
# Warming up. | ||
options = {} | ||
adapter_options = {} | ||
adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(serializers, adapter_options) | ||
serializers.serializable_hash(adapter_options, options, adapter_instance) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this |
||
|
||
# Should find something with read_multi now | ||
options = {} | ||
adapter_options = {} | ||
adapter_instance = ActiveModelSerializers::Adapter::Attributes.new(serializers, adapter_options) | ||
serializers.serializable_hash(adapter_options, options, adapter_instance) | ||
cached_attributes = adapter_options.fetch(:cached_attributes) | ||
|
||
include_directive = ActiveModelSerializers.default_include_directive | ||
manual_cached_attributes = ActiveModel::Serializer.cache_read_multi(serializers, adapter_instance, include_directive) | ||
|
||
refute_equal 0, cached_attributes.size | ||
refute_equal 0, manual_cached_attributes.size | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we assert an actual number? |
||
assert_equal manual_cached_attributes, cached_attributes | ||
end | ||
end | ||
|
||
def test_serializer_file_path_on_nix | ||
path = '/Users/git/emberjs/ember-crm-backend/app/serializers/lead_serializer.rb' | ||
caller_line = "#{path}:1:in `<top (required)>'" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You did push a lot of code that week, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did I introduce it? It seemed always broken to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hahahhahaha, when you said Ooops I figured you had. Looks like I got it wrong.