identity_cache 0.5.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/.github/probots.yml +2 -0
  3. data/.github/workflows/ci.yml +26 -0
  4. data/.gitignore +1 -0
  5. data/.rubocop.yml +5 -0
  6. data/.travis.yml +24 -9
  7. data/CHANGELOG.md +21 -0
  8. data/Gemfile +5 -1
  9. data/README.md +28 -26
  10. data/Rakefile +14 -5
  11. data/dev.yml +9 -16
  12. data/gemfiles/Gemfile.latest-release +6 -0
  13. data/gemfiles/Gemfile.rails-edge +6 -0
  14. data/gemfiles/Gemfile.rails52 +6 -0
  15. data/identity_cache.gemspec +26 -10
  16. data/lib/identity_cache.rb +49 -46
  17. data/lib/identity_cache/belongs_to_caching.rb +12 -40
  18. data/lib/identity_cache/cache_fetcher.rb +6 -5
  19. data/lib/identity_cache/cache_hash.rb +2 -2
  20. data/lib/identity_cache/cache_invalidation.rb +4 -11
  21. data/lib/identity_cache/cache_key_generation.rb +17 -65
  22. data/lib/identity_cache/cache_key_loader.rb +128 -0
  23. data/lib/identity_cache/cached.rb +7 -0
  24. data/lib/identity_cache/cached/association.rb +87 -0
  25. data/lib/identity_cache/cached/attribute.rb +123 -0
  26. data/lib/identity_cache/cached/attribute_by_multi.rb +37 -0
  27. data/lib/identity_cache/cached/attribute_by_one.rb +88 -0
  28. data/lib/identity_cache/cached/belongs_to.rb +93 -0
  29. data/lib/identity_cache/cached/embedded_fetching.rb +41 -0
  30. data/lib/identity_cache/cached/prefetcher.rb +51 -0
  31. data/lib/identity_cache/cached/primary_index.rb +97 -0
  32. data/lib/identity_cache/cached/recursive/association.rb +68 -0
  33. data/lib/identity_cache/cached/recursive/has_many.rb +9 -0
  34. data/lib/identity_cache/cached/recursive/has_one.rb +9 -0
  35. data/lib/identity_cache/cached/reference/association.rb +16 -0
  36. data/lib/identity_cache/cached/reference/has_many.rb +105 -0
  37. data/lib/identity_cache/cached/reference/has_one.rb +100 -0
  38. data/lib/identity_cache/configuration_dsl.rb +53 -215
  39. data/lib/identity_cache/encoder.rb +95 -0
  40. data/lib/identity_cache/expiry_hook.rb +36 -0
  41. data/lib/identity_cache/fallback_fetcher.rb +2 -1
  42. data/lib/identity_cache/load_strategy/eager.rb +28 -0
  43. data/lib/identity_cache/load_strategy/lazy.rb +71 -0
  44. data/lib/identity_cache/load_strategy/load_request.rb +20 -0
  45. data/lib/identity_cache/load_strategy/multi_load_request.rb +27 -0
  46. data/lib/identity_cache/memoized_cache_proxy.rb +127 -58
  47. data/lib/identity_cache/parent_model_expiration.rb +45 -11
  48. data/lib/identity_cache/query_api.rb +128 -394
  49. data/lib/identity_cache/railtie.rb +8 -0
  50. data/lib/identity_cache/record_not_found.rb +6 -0
  51. data/lib/identity_cache/should_use_cache.rb +1 -0
  52. data/lib/identity_cache/version.rb +3 -2
  53. data/lib/identity_cache/with_primary_index.rb +136 -0
  54. data/lib/identity_cache/without_primary_index.rb +24 -3
  55. data/performance/cache_runner.rb +28 -34
  56. data/performance/cpu.rb +3 -2
  57. data/performance/externals.rb +4 -3
  58. data/performance/profile.rb +6 -5
  59. data/railgun.yml +16 -0
  60. metadata +44 -73
  61. data/Gemfile.rails42 +0 -6
  62. data/Gemfile.rails50 +0 -6
  63. data/test/attribute_cache_test.rb +0 -110
  64. data/test/cache_fetch_includes_test.rb +0 -46
  65. data/test/cache_hash_test.rb +0 -14
  66. data/test/cache_invalidation_test.rb +0 -139
  67. data/test/deeply_nested_associated_record_test.rb +0 -19
  68. data/test/denormalized_has_many_test.rb +0 -214
  69. data/test/denormalized_has_one_test.rb +0 -160
  70. data/test/fetch_multi_test.rb +0 -308
  71. data/test/fetch_test.rb +0 -258
  72. data/test/fixtures/serialized_record.mysql2 +0 -0
  73. data/test/fixtures/serialized_record.postgresql +0 -0
  74. data/test/helpers/active_record_objects.rb +0 -106
  75. data/test/helpers/database_connection.rb +0 -72
  76. data/test/helpers/serialization_format.rb +0 -51
  77. data/test/helpers/update_serialization_format.rb +0 -27
  78. data/test/identity_cache_test.rb +0 -29
  79. data/test/index_cache_test.rb +0 -161
  80. data/test/memoized_attributes_test.rb +0 -59
  81. data/test/memoized_cache_proxy_test.rb +0 -107
  82. data/test/normalized_belongs_to_test.rb +0 -107
  83. data/test/normalized_has_many_test.rb +0 -231
  84. data/test/normalized_has_one_test.rb +0 -9
  85. data/test/prefetch_associations_test.rb +0 -379
  86. data/test/readonly_test.rb +0 -109
  87. data/test/recursive_denormalized_has_many_test.rb +0 -131
  88. data/test/save_test.rb +0 -82
  89. data/test/schema_change_test.rb +0 -112
  90. data/test/serialization_format_change_test.rb +0 -16
  91. data/test/test_helper.rb +0 -140
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+ module IdentityCache
3
+ class Railtie < Rails::Railtie
4
+ initializer "identity_cache.setup" do |app|
5
+ app.config.eager_load_namespaces << IdentityCache
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IdentityCache
4
+ class RecordNotFound < ActiveRecord::RecordNotFound
5
+ end
6
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module IdentityCache
2
3
  module ShouldUseCache
3
4
  extend ActiveSupport::Concern
@@ -1,4 +1,5 @@
1
+ # frozen_string_literal: true
1
2
  module IdentityCache
2
- VERSION = "0.5.1"
3
- CACHE_VERSION = 7
3
+ VERSION = "1.0.0"
4
+ CACHE_VERSION = 8
4
5
  end
@@ -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
- included do |base|
6
- base.send(:include, IdentityCache)
7
- base.primary_cache_index_enabled = false
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
@@ -1,4 +1,5 @@
1
- $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
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
- IdentityCache.cache_backend = ActiveSupport::Cache::MemcachedStore.new("localhost:#{$memcached_port}", :support_cas => true)
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(:id => (1..count)).count == count
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
- unless existing.any? { |e| e.id == i }
46
- a = Item.new
47
- a.id = i
48
- a.associated = AssociatedRecord.new(name: "Associated for #{i}")
49
- a.associated_records
50
- (1..5).each do |j|
51
- a.associated_records << AssociatedRecord.new(name: "Has Many #{j} for #{i}")
52
- a.normalized_associated_records << NormalizedAssociatedRecord.new(name: "Normalized Has Many #{j} for #{i}")
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 :associated
63
- Item.cache_has_many :associated_records, :embed => true
64
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
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, {:associated_records => :deeply_associated_records}).find(i)
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).send(:expire_cache) }
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].send(:expire_cache)
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).send(:expire_cache) }
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 :associated
142
- Item.cache_has_many :associated_records, :embed => true
143
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => true
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 :associated # :embed => false isn't supported
184
- Item.cache_has_many :associated_records, :embed => :ids
185
- AssociatedRecord.cache_has_many :deeply_associated_records, :embed => :ids
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
@@ -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, '-')
@@ -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
- "Database" => ["Mysql2::Client#query"]}
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
@@ -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 1
30
+ exit(1)
30
31
  end
31
32
  else
32
- CACHE_RUNNERS.each do |runner|
33
- run(runner.new(RUNS))
33
+ CACHE_RUNNERS.each do |cache_runner|
34
+ run(cache_runner.new(RUNS))
34
35
  end
35
36
  end
@@ -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.5.1
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: 2017-02-09 00:00:00.000000000 Z
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: 4.2.0
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: 4.2.0
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 in read through ActiveRecord caching.
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.2.0
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
- rubyforge_project:
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: []