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.
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: []