identity_cache 0.5.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/probots.yml +2 -0
- data/.github/workflows/ci.yml +26 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +24 -9
- data/CHANGELOG.md +21 -0
- data/Gemfile +5 -1
- data/README.md +28 -26
- data/Rakefile +14 -5
- data/dev.yml +9 -16
- data/gemfiles/Gemfile.latest-release +6 -0
- data/gemfiles/Gemfile.rails-edge +6 -0
- data/gemfiles/Gemfile.rails52 +6 -0
- data/identity_cache.gemspec +26 -10
- data/lib/identity_cache.rb +49 -46
- data/lib/identity_cache/belongs_to_caching.rb +12 -40
- data/lib/identity_cache/cache_fetcher.rb +6 -5
- data/lib/identity_cache/cache_hash.rb +2 -2
- data/lib/identity_cache/cache_invalidation.rb +4 -11
- data/lib/identity_cache/cache_key_generation.rb +17 -65
- data/lib/identity_cache/cache_key_loader.rb +128 -0
- data/lib/identity_cache/cached.rb +7 -0
- data/lib/identity_cache/cached/association.rb +87 -0
- data/lib/identity_cache/cached/attribute.rb +123 -0
- data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
- data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
- data/lib/identity_cache/cached/belongs_to.rb +93 -0
- data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
- data/lib/identity_cache/cached/prefetcher.rb +51 -0
- data/lib/identity_cache/cached/primary_index.rb +97 -0
- data/lib/identity_cache/cached/recursive/association.rb +68 -0
- data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
- data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
- data/lib/identity_cache/cached/reference/association.rb +16 -0
- data/lib/identity_cache/cached/reference/has_many.rb +105 -0
- data/lib/identity_cache/cached/reference/has_one.rb +100 -0
- data/lib/identity_cache/configuration_dsl.rb +53 -215
- data/lib/identity_cache/encoder.rb +95 -0
- data/lib/identity_cache/expiry_hook.rb +36 -0
- data/lib/identity_cache/fallback_fetcher.rb +2 -1
- data/lib/identity_cache/load_strategy/eager.rb +28 -0
- data/lib/identity_cache/load_strategy/lazy.rb +71 -0
- data/lib/identity_cache/load_strategy/load_request.rb +20 -0
- data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
- data/lib/identity_cache/memoized_cache_proxy.rb +127 -58
- data/lib/identity_cache/parent_model_expiration.rb +45 -11
- data/lib/identity_cache/query_api.rb +128 -394
- data/lib/identity_cache/railtie.rb +8 -0
- data/lib/identity_cache/record_not_found.rb +6 -0
- data/lib/identity_cache/should_use_cache.rb +1 -0
- data/lib/identity_cache/version.rb +3 -2
- data/lib/identity_cache/with_primary_index.rb +136 -0
- data/lib/identity_cache/without_primary_index.rb +24 -3
- data/performance/cache_runner.rb +28 -34
- data/performance/cpu.rb +3 -2
- data/performance/externals.rb +4 -3
- data/performance/profile.rb +6 -5
- data/railgun.yml +16 -0
- metadata +44 -73
- data/Gemfile.rails42 +0 -6
- data/Gemfile.rails50 +0 -6
- data/test/attribute_cache_test.rb +0 -110
- data/test/cache_fetch_includes_test.rb +0 -46
- data/test/cache_hash_test.rb +0 -14
- data/test/cache_invalidation_test.rb +0 -139
- data/test/deeply_nested_associated_record_test.rb +0 -19
- data/test/denormalized_has_many_test.rb +0 -214
- data/test/denormalized_has_one_test.rb +0 -160
- data/test/fetch_multi_test.rb +0 -308
- data/test/fetch_test.rb +0 -258
- data/test/fixtures/serialized_record.mysql2 +0 -0
- data/test/fixtures/serialized_record.postgresql +0 -0
- data/test/helpers/active_record_objects.rb +0 -106
- data/test/helpers/database_connection.rb +0 -72
- data/test/helpers/serialization_format.rb +0 -51
- data/test/helpers/update_serialization_format.rb +0 -27
- data/test/identity_cache_test.rb +0 -29
- data/test/index_cache_test.rb +0 -161
- data/test/memoized_attributes_test.rb +0 -59
- data/test/memoized_cache_proxy_test.rb +0 -107
- data/test/normalized_belongs_to_test.rb +0 -107
- data/test/normalized_has_many_test.rb +0 -231
- data/test/normalized_has_one_test.rb +0 -9
- data/test/prefetch_associations_test.rb +0 -379
- data/test/readonly_test.rb +0 -109
- data/test/recursive_denormalized_has_many_test.rb +0 -131
- data/test/save_test.rb +0 -82
- data/test/schema_change_test.rb +0 -112
- data/test/serialization_format_change_test.rb +0 -16
- data/test/test_helper.rb +0 -140
@@ -0,0 +1,136 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module IdentityCache
|
3
|
+
module WithPrimaryIndex
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
include WithoutPrimaryIndex
|
7
|
+
|
8
|
+
def expire_cache
|
9
|
+
expire_primary_index
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
# @api private
|
14
|
+
def expire_primary_index # :nodoc:
|
15
|
+
self.class.expire_primary_key_cache_index(id)
|
16
|
+
end
|
17
|
+
|
18
|
+
# @api private
|
19
|
+
def primary_cache_index_key # :nodoc:
|
20
|
+
self.class.cached_primary_index.cache_key(id)
|
21
|
+
end
|
22
|
+
|
23
|
+
module ClassMethods
|
24
|
+
# @api private
|
25
|
+
def cached_primary_index
|
26
|
+
@cached_primary_index ||= Cached::PrimaryIndex.new(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def primary_cache_index_enabled
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# Declares a new index in the cache for the class where IdentityCache was
|
34
|
+
# included.
|
35
|
+
#
|
36
|
+
# IdentityCache will add a fetch_by_field1_and_field2_and_...field for every
|
37
|
+
# index.
|
38
|
+
#
|
39
|
+
# == Example:
|
40
|
+
#
|
41
|
+
# class Product
|
42
|
+
# include IdentityCache
|
43
|
+
# cache_index :name, :vendor
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# Will add Product.fetch_by_name_and_vendor
|
47
|
+
#
|
48
|
+
# == Parameters
|
49
|
+
#
|
50
|
+
# +fields+ Array of symbols or strings representing the fields in the index
|
51
|
+
#
|
52
|
+
# == Options
|
53
|
+
# * unique: if the index would only have unique values. Default is false
|
54
|
+
#
|
55
|
+
def cache_index(*fields, unique: false)
|
56
|
+
attribute_proc = -> { primary_key }
|
57
|
+
cache_attribute_by_alias(attribute_proc, alias_name: :id, by: fields, unique: unique)
|
58
|
+
|
59
|
+
field_list = fields.join("_and_")
|
60
|
+
arg_list = (0...fields.size).collect { |i| "arg#{i}" }.join(',')
|
61
|
+
|
62
|
+
if unique
|
63
|
+
instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
|
64
|
+
def fetch_by_#{field_list}(#{arg_list}, includes: nil)
|
65
|
+
id = fetch_id_by_#{field_list}(#{arg_list})
|
66
|
+
id && fetch_by_id(id, includes: includes)
|
67
|
+
end
|
68
|
+
|
69
|
+
# exception throwing variant
|
70
|
+
def fetch_by_#{field_list}!(#{arg_list}, includes: nil)
|
71
|
+
fetch_by_#{field_list}(#{arg_list}, includes: includes) or raise IdentityCache::RecordNotFound
|
72
|
+
end
|
73
|
+
CODE
|
74
|
+
else
|
75
|
+
instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
|
76
|
+
def fetch_by_#{field_list}(#{arg_list}, includes: nil)
|
77
|
+
ids = fetch_id_by_#{field_list}(#{arg_list})
|
78
|
+
ids.empty? ? ids : fetch_multi(ids, includes: includes)
|
79
|
+
end
|
80
|
+
CODE
|
81
|
+
end
|
82
|
+
|
83
|
+
if fields.length == 1
|
84
|
+
instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
|
85
|
+
def fetch_multi_by_#{field_list}(index_values, includes: nil)
|
86
|
+
ids = fetch_multi_id_by_#{field_list}(index_values).values.flatten(1)
|
87
|
+
return ids if ids.empty?
|
88
|
+
fetch_multi(ids, includes: includes)
|
89
|
+
end
|
90
|
+
CODE
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Similar to ActiveRecord::Base#exists? will return true if the id can be
|
95
|
+
# found in the cache or in the DB.
|
96
|
+
def exists_with_identity_cache?(id)
|
97
|
+
!!fetch_by_id(id)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Default fetcher added to the model on inclusion, it behaves like
|
101
|
+
# ActiveRecord::Base.where(id: id).first
|
102
|
+
def fetch_by_id(id, includes: nil)
|
103
|
+
ensure_base_model
|
104
|
+
raise_if_scoped
|
105
|
+
record = cached_primary_index.fetch(id)
|
106
|
+
prefetch_associations(includes, [record]) if record && includes
|
107
|
+
record
|
108
|
+
end
|
109
|
+
|
110
|
+
# Default fetcher added to the model on inclusion, it behaves like
|
111
|
+
# ActiveRecord::Base.find, but will raise IdentityCache::RecordNotFound
|
112
|
+
# if the id is not in the cache.
|
113
|
+
def fetch(id, includes: nil)
|
114
|
+
fetch_by_id(id, includes: includes) || raise(
|
115
|
+
IdentityCache::RecordNotFound, "Couldn't find #{name} with ID=#{id}"
|
116
|
+
)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Default fetcher added to the model on inclusion, if behaves like
|
120
|
+
# ActiveRecord::Base.find_all_by_id
|
121
|
+
def fetch_multi(*ids, includes: nil)
|
122
|
+
ensure_base_model
|
123
|
+
raise_if_scoped
|
124
|
+
ids.flatten!(1)
|
125
|
+
records = cached_primary_index.fetch_multi(ids)
|
126
|
+
prefetch_associations(includes, records) if includes
|
127
|
+
records
|
128
|
+
end
|
129
|
+
|
130
|
+
# Invalidates the primary cache index for the associated record. Will not invalidate cached attributes.
|
131
|
+
def expire_primary_key_cache_index(id)
|
132
|
+
cached_primary_index.expire(id)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -1,10 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module IdentityCache
|
2
3
|
module WithoutPrimaryIndex
|
3
4
|
extend ActiveSupport::Concern
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
include ArTransactionChanges
|
7
|
+
include IdentityCache::BelongsToCaching
|
8
|
+
include IdentityCache::CacheKeyGeneration
|
9
|
+
include IdentityCache::ConfigurationDSL
|
10
|
+
include IdentityCache::QueryAPI
|
11
|
+
include IdentityCache::CacheInvalidation
|
12
|
+
include IdentityCache::ShouldUseCache
|
13
|
+
include ParentModelExpiration
|
14
|
+
|
15
|
+
def self.append_features(base) #:nodoc:
|
16
|
+
raise AlreadyIncludedError if base.include?(WithoutPrimaryIndex)
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
included do
|
21
|
+
class_attribute(:cached_model)
|
22
|
+
self.cached_model = self
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
def primary_cache_index_enabled
|
27
|
+
false
|
28
|
+
end
|
8
29
|
end
|
9
30
|
end
|
10
31
|
end
|
data/performance/cache_runner.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
$LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
|
2
3
|
require 'active_record'
|
3
4
|
require 'active_support/core_ext'
|
4
5
|
require 'active_support/cache'
|
@@ -6,25 +7,19 @@ require 'identity_cache'
|
|
6
7
|
require 'memcached_store'
|
7
8
|
require 'active_support/cache/memcached_store'
|
8
9
|
|
9
|
-
$memcached_port = 11211
|
10
|
-
$mysql_port = 3306
|
11
|
-
|
12
10
|
require File.dirname(__FILE__) + '/../test/helpers/active_record_objects'
|
13
11
|
require File.dirname(__FILE__) + '/../test/helpers/database_connection'
|
12
|
+
require File.dirname(__FILE__) + '/../test/helpers/cache_connection'
|
14
13
|
|
15
14
|
IdentityCache.logger = Logger.new(nil)
|
16
|
-
|
17
|
-
|
18
|
-
if ActiveRecord.gem_version < Gem::Version.new('5') && ActiveRecord::Base.respond_to?(:raise_in_transactional_callbacks=)
|
19
|
-
ActiveRecord::Base.raise_in_transactional_callbacks = true
|
20
|
-
end
|
15
|
+
CacheConnection.setup
|
21
16
|
|
22
17
|
def create_record(id)
|
23
18
|
Item.new(id)
|
24
19
|
end
|
25
20
|
|
26
21
|
def database_ready(count)
|
27
|
-
Item.where(:
|
22
|
+
Item.where(id: (1..count)).count == count
|
28
23
|
rescue
|
29
24
|
false
|
30
25
|
end
|
@@ -42,26 +37,25 @@ def create_database(count)
|
|
42
37
|
DatabaseConnection.create_tables
|
43
38
|
existing = Item.all
|
44
39
|
(1..count).to_a.each do |i|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
a.save
|
40
|
+
next if existing.any? { |e| e.id == i }
|
41
|
+
a = Item.new
|
42
|
+
a.id = i
|
43
|
+
a.associated = AssociatedRecord.new(name: "Associated for #{i}")
|
44
|
+
a.associated_records
|
45
|
+
(1..5).each do |j|
|
46
|
+
a.associated_records << AssociatedRecord.new(name: "Has Many #{j} for #{i}")
|
47
|
+
a.normalized_associated_records << NormalizedAssociatedRecord.new(name: "Normalized Has Many #{j} for #{i}")
|
55
48
|
end
|
49
|
+
a.save
|
56
50
|
end
|
57
51
|
ensure
|
58
52
|
helper.teardown_models
|
59
53
|
end
|
60
54
|
|
61
55
|
def setup_embedded_associations
|
62
|
-
Item.cache_has_one :
|
63
|
-
Item.cache_has_many
|
64
|
-
AssociatedRecord.cache_has_many
|
56
|
+
Item.cache_has_one(:associated, embed: true)
|
57
|
+
Item.cache_has_many(:associated_records, embed: true)
|
58
|
+
AssociatedRecord.cache_has_many(:deeply_associated_records, embed: true)
|
65
59
|
end
|
66
60
|
|
67
61
|
class CacheRunner
|
@@ -86,7 +80,7 @@ CACHE_RUNNERS = []
|
|
86
80
|
class FindRunner < CacheRunner
|
87
81
|
def run
|
88
82
|
(1..@count).each do |i|
|
89
|
-
::Item.includes(:associated,
|
83
|
+
::Item.includes(:associated, associated_records: :deeply_associated_records).find(i)
|
90
84
|
end
|
91
85
|
end
|
92
86
|
end
|
@@ -109,18 +103,18 @@ end
|
|
109
103
|
module DeletedRunner
|
110
104
|
def prepare
|
111
105
|
super
|
112
|
-
(1..@count).each {|i| ::Item.find(i).
|
106
|
+
(1..@count).each { |i| ::Item.find(i).expire_cache }
|
113
107
|
end
|
114
108
|
end
|
115
109
|
|
116
110
|
module ConflictRunner
|
117
111
|
def prepare
|
118
112
|
super
|
119
|
-
records = (1..@count).map {|id| ::Item.find(id) }
|
113
|
+
records = (1..@count).map { |id| ::Item.find(id) }
|
120
114
|
orig_resolve_cache_miss = ::Item.method(:resolve_cache_miss)
|
121
115
|
|
122
116
|
::Item.define_singleton_method(:resolve_cache_miss) do |id|
|
123
|
-
records[id-1].
|
117
|
+
records[id - 1].expire_cache
|
124
118
|
orig_resolve_cache_miss.call(id)
|
125
119
|
end
|
126
120
|
IdentityCache.cache.clear
|
@@ -131,16 +125,16 @@ module DeletedConflictRunner
|
|
131
125
|
include ConflictRunner
|
132
126
|
def prepare
|
133
127
|
super
|
134
|
-
(1..@count).each {|i| ::Item.find(i).
|
128
|
+
(1..@count).each { |i| ::Item.find(i).expire_cache }
|
135
129
|
end
|
136
130
|
end
|
137
131
|
|
138
132
|
class EmbedRunner < CacheRunner
|
139
133
|
def setup_models
|
140
134
|
super
|
141
|
-
Item.cache_has_one :
|
142
|
-
Item.cache_has_many
|
143
|
-
AssociatedRecord.cache_has_many
|
135
|
+
Item.cache_has_one(:associated, embed: true)
|
136
|
+
Item.cache_has_many(:associated_records, embed: true)
|
137
|
+
AssociatedRecord.cache_has_many(:deeply_associated_records, embed: true)
|
144
138
|
end
|
145
139
|
|
146
140
|
def run
|
@@ -180,9 +174,9 @@ CACHE_RUNNERS << FetchEmbedDeletedConflictRunner
|
|
180
174
|
class NormalizedRunner < CacheRunner
|
181
175
|
def setup_models
|
182
176
|
super
|
183
|
-
Item.cache_has_one
|
184
|
-
Item.cache_has_many
|
185
|
-
AssociatedRecord.cache_has_many
|
177
|
+
Item.cache_has_one(:associated, embed: :id)
|
178
|
+
Item.cache_has_many(:associated_records, embed: :ids)
|
179
|
+
AssociatedRecord.cache_has_many(:deeply_associated_records, embed: :ids)
|
186
180
|
end
|
187
181
|
|
188
182
|
def run
|
data/performance/cpu.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rubygems'
|
2
3
|
require 'benchmark'
|
3
4
|
|
@@ -19,7 +20,7 @@ ensure
|
|
19
20
|
obj.cleanup
|
20
21
|
end
|
21
22
|
|
22
|
-
def benchmark(runners, label_width=0)
|
23
|
+
def benchmark(runners, label_width = 0)
|
23
24
|
IdentityCache.cache.clear
|
24
25
|
runners.each do |runner|
|
25
26
|
print "#{runner.name}: ".ljust(label_width)
|
@@ -28,7 +29,7 @@ def benchmark(runners, label_width=0)
|
|
28
29
|
end
|
29
30
|
|
30
31
|
def bmbm(runners)
|
31
|
-
label_width = runners.map{ |r| r.name.size }.max + 2
|
32
|
+
label_width = runners.map { |r| r.name.size }.max + 2
|
32
33
|
width = label_width + Benchmark::CAPTION.size
|
33
34
|
|
34
35
|
puts 'Rehearsal: '.ljust(width, '-')
|
data/performance/externals.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rubygems'
|
2
3
|
require 'benchmark'
|
3
4
|
require 'ruby-prof'
|
@@ -7,8 +8,8 @@ require_relative 'cache_runner'
|
|
7
8
|
RUNS = 1000
|
8
9
|
RubyProf.measure_mode = RubyProf::CPU_TIME
|
9
10
|
|
10
|
-
EXTERNALS = {"Memcache" => ["MemCache#set", "MemCache#get"],
|
11
|
-
|
11
|
+
EXTERNALS = { "Memcache" => ["MemCache#set", "MemCache#get"],
|
12
|
+
"Database" => ["Mysql2::Client#query"] }
|
12
13
|
|
13
14
|
def run(obj)
|
14
15
|
obj.prepare
|
@@ -26,7 +27,7 @@ def count_externals(results)
|
|
26
27
|
count = {}
|
27
28
|
results.split(/\n/).each do |line|
|
28
29
|
fields = line.split
|
29
|
-
if ext = EXTERNALS.detect { |e| e[1].any? { |method| method == fields[-1] } }
|
30
|
+
if (ext = EXTERNALS.detect { |e| e[1].any? { |method| method == fields[-1] } })
|
30
31
|
count[ext[0]] ||= 0
|
31
32
|
count[ext[0]] += fields[-2].to_i
|
32
33
|
end
|
data/performance/profile.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rubygems'
|
2
3
|
require 'benchmark'
|
3
4
|
require 'stackprof'
|
@@ -21,15 +22,15 @@ end
|
|
21
22
|
|
22
23
|
create_database(RUNS)
|
23
24
|
|
24
|
-
if runner_name = ENV['RUNNER']
|
25
|
-
if runner = CACHE_RUNNERS.find{ |r| r.name == runner_name }
|
25
|
+
if (runner_name = ENV['RUNNER'])
|
26
|
+
if (runner = CACHE_RUNNERS.find { |r| r.name == runner_name })
|
26
27
|
run(runner.new(RUNS), filename: ENV['FILENAME'])
|
27
28
|
else
|
28
29
|
puts "Couldn't find cache runner #{runner_name.inspect}"
|
29
|
-
exit
|
30
|
+
exit(1)
|
30
31
|
end
|
31
32
|
else
|
32
|
-
CACHE_RUNNERS.each do |
|
33
|
-
run(
|
33
|
+
CACHE_RUNNERS.each do |cache_runner|
|
34
|
+
run(cache_runner.new(RUNS))
|
34
35
|
end
|
35
36
|
end
|
data/railgun.yml
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# https://dev-accel.shopify.io/dev/railgun/Railgun-Config
|
2
|
+
name: identity-cache
|
3
|
+
|
4
|
+
vm:
|
5
|
+
image: /opt/dev/misc/railgun-images/default
|
6
|
+
ip_address: 192.168.64.98
|
7
|
+
memory: 1G
|
8
|
+
cores: 2
|
9
|
+
|
10
|
+
volumes:
|
11
|
+
root: 1G
|
12
|
+
|
13
|
+
services:
|
14
|
+
- mysql
|
15
|
+
- postgresql
|
16
|
+
- memcached
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: identity_cache
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Camilo Lopez
|
@@ -14,7 +14,7 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
|
-
date:
|
17
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
19
|
- !ruby/object:Gem::Dependency
|
20
20
|
name: ar_transaction_changes
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
39
|
+
version: '5.2'
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
46
|
+
version: '5.2'
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: memcached
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
@@ -160,16 +160,16 @@ dependencies:
|
|
160
160
|
name: pg
|
161
161
|
requirement: !ruby/object:Gem::Requirement
|
162
162
|
requirements:
|
163
|
-
- - "
|
163
|
+
- - "~>"
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: '0'
|
165
|
+
version: '0.18'
|
166
166
|
type: :development
|
167
167
|
prerelease: false
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
169
169
|
requirements:
|
170
|
-
- - "
|
170
|
+
- - "~>"
|
171
171
|
- !ruby/object:Gem::Version
|
172
|
-
version: '0'
|
172
|
+
version: '0.18'
|
173
173
|
- !ruby/object:Gem::Dependency
|
174
174
|
name: stackprof
|
175
175
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,24 +184,28 @@ dependencies:
|
|
184
184
|
- - ">="
|
185
185
|
- !ruby/object:Gem::Version
|
186
186
|
version: '0'
|
187
|
-
description: Opt
|
187
|
+
description: Opt-in read through Active Record caching.
|
188
188
|
email:
|
189
189
|
- gems@shopify.com
|
190
190
|
executables: []
|
191
191
|
extensions: []
|
192
192
|
extra_rdoc_files: []
|
193
193
|
files:
|
194
|
+
- ".github/probots.yml"
|
195
|
+
- ".github/workflows/ci.yml"
|
194
196
|
- ".gitignore"
|
197
|
+
- ".rubocop.yml"
|
195
198
|
- ".travis.yml"
|
196
199
|
- CHANGELOG.md
|
197
200
|
- CONTRIBUTING.md
|
198
201
|
- Gemfile
|
199
|
-
- Gemfile.rails42
|
200
|
-
- Gemfile.rails50
|
201
202
|
- LICENSE
|
202
203
|
- README.md
|
203
204
|
- Rakefile
|
204
205
|
- dev.yml
|
206
|
+
- gemfiles/Gemfile.latest-release
|
207
|
+
- gemfiles/Gemfile.rails-edge
|
208
|
+
- gemfiles/Gemfile.rails52
|
205
209
|
- identity_cache.gemspec
|
206
210
|
- lib/identity_cache.rb
|
207
211
|
- lib/identity_cache/belongs_to_caching.rb
|
@@ -209,48 +213,45 @@ files:
|
|
209
213
|
- lib/identity_cache/cache_hash.rb
|
210
214
|
- lib/identity_cache/cache_invalidation.rb
|
211
215
|
- lib/identity_cache/cache_key_generation.rb
|
216
|
+
- lib/identity_cache/cache_key_loader.rb
|
217
|
+
- lib/identity_cache/cached.rb
|
218
|
+
- lib/identity_cache/cached/association.rb
|
219
|
+
- lib/identity_cache/cached/attribute.rb
|
220
|
+
- lib/identity_cache/cached/attribute_by_multi.rb
|
221
|
+
- lib/identity_cache/cached/attribute_by_one.rb
|
222
|
+
- lib/identity_cache/cached/belongs_to.rb
|
223
|
+
- lib/identity_cache/cached/embedded_fetching.rb
|
224
|
+
- lib/identity_cache/cached/prefetcher.rb
|
225
|
+
- lib/identity_cache/cached/primary_index.rb
|
226
|
+
- lib/identity_cache/cached/recursive/association.rb
|
227
|
+
- lib/identity_cache/cached/recursive/has_many.rb
|
228
|
+
- lib/identity_cache/cached/recursive/has_one.rb
|
229
|
+
- lib/identity_cache/cached/reference/association.rb
|
230
|
+
- lib/identity_cache/cached/reference/has_many.rb
|
231
|
+
- lib/identity_cache/cached/reference/has_one.rb
|
212
232
|
- lib/identity_cache/configuration_dsl.rb
|
233
|
+
- lib/identity_cache/encoder.rb
|
234
|
+
- lib/identity_cache/expiry_hook.rb
|
213
235
|
- lib/identity_cache/fallback_fetcher.rb
|
236
|
+
- lib/identity_cache/load_strategy/eager.rb
|
237
|
+
- lib/identity_cache/load_strategy/lazy.rb
|
238
|
+
- lib/identity_cache/load_strategy/load_request.rb
|
239
|
+
- lib/identity_cache/load_strategy/multi_load_request.rb
|
214
240
|
- lib/identity_cache/memoized_cache_proxy.rb
|
215
241
|
- lib/identity_cache/parent_model_expiration.rb
|
216
242
|
- lib/identity_cache/query_api.rb
|
243
|
+
- lib/identity_cache/railtie.rb
|
244
|
+
- lib/identity_cache/record_not_found.rb
|
217
245
|
- lib/identity_cache/should_use_cache.rb
|
218
246
|
- lib/identity_cache/version.rb
|
247
|
+
- lib/identity_cache/with_primary_index.rb
|
219
248
|
- lib/identity_cache/without_primary_index.rb
|
220
249
|
- performance/cache_runner.rb
|
221
250
|
- performance/cpu.rb
|
222
251
|
- performance/externals.rb
|
223
252
|
- performance/profile.rb
|
253
|
+
- railgun.yml
|
224
254
|
- shipit.rubygems.yml
|
225
|
-
- test/attribute_cache_test.rb
|
226
|
-
- test/cache_fetch_includes_test.rb
|
227
|
-
- test/cache_hash_test.rb
|
228
|
-
- test/cache_invalidation_test.rb
|
229
|
-
- test/deeply_nested_associated_record_test.rb
|
230
|
-
- test/denormalized_has_many_test.rb
|
231
|
-
- test/denormalized_has_one_test.rb
|
232
|
-
- test/fetch_multi_test.rb
|
233
|
-
- test/fetch_test.rb
|
234
|
-
- test/fixtures/serialized_record.mysql2
|
235
|
-
- test/fixtures/serialized_record.postgresql
|
236
|
-
- test/helpers/active_record_objects.rb
|
237
|
-
- test/helpers/database_connection.rb
|
238
|
-
- test/helpers/serialization_format.rb
|
239
|
-
- test/helpers/update_serialization_format.rb
|
240
|
-
- test/identity_cache_test.rb
|
241
|
-
- test/index_cache_test.rb
|
242
|
-
- test/memoized_attributes_test.rb
|
243
|
-
- test/memoized_cache_proxy_test.rb
|
244
|
-
- test/normalized_belongs_to_test.rb
|
245
|
-
- test/normalized_has_many_test.rb
|
246
|
-
- test/normalized_has_one_test.rb
|
247
|
-
- test/prefetch_associations_test.rb
|
248
|
-
- test/readonly_test.rb
|
249
|
-
- test/recursive_denormalized_has_many_test.rb
|
250
|
-
- test/save_test.rb
|
251
|
-
- test/schema_change_test.rb
|
252
|
-
- test/serialization_format_change_test.rb
|
253
|
-
- test/test_helper.rb
|
254
255
|
homepage: https://github.com/Shopify/identity_cache
|
255
256
|
licenses: []
|
256
257
|
metadata: {}
|
@@ -262,48 +263,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
262
263
|
requirements:
|
263
264
|
- - ">="
|
264
265
|
- !ruby/object:Gem::Version
|
265
|
-
version: 2.
|
266
|
+
version: 2.4.0
|
266
267
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
267
268
|
requirements:
|
268
269
|
- - ">="
|
269
270
|
- !ruby/object:Gem::Version
|
270
271
|
version: '0'
|
271
272
|
requirements: []
|
272
|
-
|
273
|
-
rubygems_version: 2.5.2
|
273
|
+
rubygems_version: 3.0.3
|
274
274
|
signing_key:
|
275
275
|
specification_version: 4
|
276
276
|
summary: IdentityCache lets you specify how you want to cache your model objects,
|
277
277
|
at the model level, and adds a number of convenience methods for accessing those
|
278
278
|
objects through the cache. Memcached is used as the backend cache store, and the
|
279
279
|
database is only hit when a copy of the object cannot be found in Memcached.
|
280
|
-
test_files:
|
281
|
-
- test/attribute_cache_test.rb
|
282
|
-
- test/cache_fetch_includes_test.rb
|
283
|
-
- test/cache_hash_test.rb
|
284
|
-
- test/cache_invalidation_test.rb
|
285
|
-
- test/deeply_nested_associated_record_test.rb
|
286
|
-
- test/denormalized_has_many_test.rb
|
287
|
-
- test/denormalized_has_one_test.rb
|
288
|
-
- test/fetch_multi_test.rb
|
289
|
-
- test/fetch_test.rb
|
290
|
-
- test/fixtures/serialized_record.mysql2
|
291
|
-
- test/fixtures/serialized_record.postgresql
|
292
|
-
- test/helpers/active_record_objects.rb
|
293
|
-
- test/helpers/database_connection.rb
|
294
|
-
- test/helpers/serialization_format.rb
|
295
|
-
- test/helpers/update_serialization_format.rb
|
296
|
-
- test/identity_cache_test.rb
|
297
|
-
- test/index_cache_test.rb
|
298
|
-
- test/memoized_attributes_test.rb
|
299
|
-
- test/memoized_cache_proxy_test.rb
|
300
|
-
- test/normalized_belongs_to_test.rb
|
301
|
-
- test/normalized_has_many_test.rb
|
302
|
-
- test/normalized_has_one_test.rb
|
303
|
-
- test/prefetch_associations_test.rb
|
304
|
-
- test/readonly_test.rb
|
305
|
-
- test/recursive_denormalized_has_many_test.rb
|
306
|
-
- test/save_test.rb
|
307
|
-
- test/schema_change_test.rb
|
308
|
-
- test/serialization_format_change_test.rb
|
309
|
-
- test/test_helper.rb
|
280
|
+
test_files: []
|