identity_cache 1.1.0 → 1.2.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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +5 -4
  3. data/.github/workflows/cla.yml +22 -0
  4. data/.rubocop.yml +7 -3
  5. data/.spin/bootstrap +7 -0
  6. data/.spin/svc.yml +2 -0
  7. data/CHANGELOG.md +10 -0
  8. data/Gemfile +15 -5
  9. data/LICENSE +1 -1
  10. data/README.md +5 -6
  11. data/Rakefile +13 -12
  12. data/dev.yml +2 -4
  13. data/gemfiles/Gemfile.latest-release +12 -7
  14. data/gemfiles/Gemfile.min-supported +11 -6
  15. data/gemfiles/Gemfile.rails-edge +8 -5
  16. data/identity_cache.gemspec +15 -27
  17. data/{railgun.yml → isogun.yml} +0 -5
  18. data/lib/identity_cache/belongs_to_caching.rb +1 -0
  19. data/lib/identity_cache/cache_fetcher.rb +241 -16
  20. data/lib/identity_cache/cache_hash.rb +7 -6
  21. data/lib/identity_cache/cache_invalidation.rb +1 -0
  22. data/lib/identity_cache/cache_key_generation.rb +22 -19
  23. data/lib/identity_cache/cache_key_loader.rb +2 -2
  24. data/lib/identity_cache/cached/association.rb +2 -4
  25. data/lib/identity_cache/cached/attribute.rb +3 -3
  26. data/lib/identity_cache/cached/attribute_by_multi.rb +1 -1
  27. data/lib/identity_cache/cached/belongs_to.rb +3 -0
  28. data/lib/identity_cache/cached/embedded_fetching.rb +2 -0
  29. data/lib/identity_cache/cached/primary_index.rb +3 -2
  30. data/lib/identity_cache/cached/recursive/association.rb +2 -0
  31. data/lib/identity_cache/cached/recursive/has_many.rb +1 -0
  32. data/lib/identity_cache/cached/recursive/has_one.rb +1 -0
  33. data/lib/identity_cache/cached/reference/association.rb +1 -0
  34. data/lib/identity_cache/cached/reference/has_many.rb +1 -0
  35. data/lib/identity_cache/cached/reference/has_one.rb +1 -0
  36. data/lib/identity_cache/cached.rb +1 -0
  37. data/lib/identity_cache/configuration_dsl.rb +1 -0
  38. data/lib/identity_cache/encoder.rb +2 -1
  39. data/lib/identity_cache/expiry_hook.rb +1 -0
  40. data/lib/identity_cache/fallback_fetcher.rb +6 -1
  41. data/lib/identity_cache/mem_cache_store_cas.rb +15 -5
  42. data/lib/identity_cache/memoized_cache_proxy.rb +15 -15
  43. data/lib/identity_cache/parent_model_expiration.rb +3 -1
  44. data/lib/identity_cache/query_api.rb +3 -0
  45. data/lib/identity_cache/railtie.rb +1 -0
  46. data/lib/identity_cache/should_use_cache.rb +1 -0
  47. data/lib/identity_cache/version.rb +2 -1
  48. data/lib/identity_cache/with_primary_index.rb +37 -10
  49. data/lib/identity_cache/without_primary_index.rb +7 -3
  50. data/lib/identity_cache.rb +38 -24
  51. data/performance/cache_runner.rb +12 -9
  52. data/performance/cpu.rb +6 -5
  53. data/performance/externals.rb +6 -5
  54. data/performance/profile.rb +7 -6
  55. metadata +27 -123
  56. data/.github/probots.yml +0 -2
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require 'monitor'
3
- require 'benchmark'
2
+
3
+ require "monitor"
4
+ require "benchmark"
4
5
 
5
6
  module IdentityCache
6
7
  class MemoizedCacheProxy
@@ -12,7 +13,7 @@ module IdentityCache
12
13
  end
13
14
 
14
15
  def cache_backend=(cache_adaptor)
15
- if cache_adaptor.class.name == 'ActiveSupport::Cache::MemCacheStore'
16
+ if cache_adaptor.class.name == "ActiveSupport::Cache::MemCacheStore"
16
17
  if cache_adaptor.respond_to?(:cas) || cache_adaptor.respond_to?(:cas_multi)
17
18
  unless cache_adaptor.is_a?(MemCacheStoreCAS)
18
19
  raise "#{cache_adaptor} respond to :cas or :cas_multi, that's unexpected"
@@ -30,7 +31,7 @@ module IdentityCache
30
31
  # no need for CAS support
31
32
  else
32
33
  warn("[IdentityCache] Missing CAS support in cache backend #{cache_adaptor.class} "\
33
- "which is needed for cache consistency")
34
+ "which is needed for cache consistency")
34
35
  end
35
36
  @cache_fetcher = FallbackFetcher.new(cache_adaptor)
36
37
  end
@@ -50,7 +51,7 @@ module IdentityCache
50
51
 
51
52
  def write(key, value)
52
53
  memoizing = memoizing?
53
- ActiveSupport::Notifications.instrument('cache_write.identity_cache', memoizing: memoizing) do
54
+ ActiveSupport::Notifications.instrument("cache_write.identity_cache", memoizing: memoizing) do
54
55
  memoized_key_values[key] = value if memoizing
55
56
  @cache_fetcher.write(key, value)
56
57
  end
@@ -58,7 +59,7 @@ module IdentityCache
58
59
 
59
60
  def delete(key)
60
61
  memoizing = memoizing?
61
- ActiveSupport::Notifications.instrument('cache_delete.identity_cache', memoizing: memoizing) do
62
+ ActiveSupport::Notifications.instrument("cache_delete.identity_cache", memoizing: memoizing) do
62
63
  memoized_key_values.delete(key) if memoizing
63
64
  if (result = @cache_fetcher.delete(key))
64
65
  IdentityCache.logger.debug { "[IdentityCache] delete recorded for #{key}" }
@@ -69,20 +70,18 @@ module IdentityCache
69
70
  end
70
71
  end
71
72
 
72
- def fetch(key)
73
+ def fetch(key, cache_fetcher_options = {}, &block)
73
74
  memo_misses = 0
74
75
  cache_misses = 0
75
76
 
76
- value = ActiveSupport::Notifications.instrument('cache_fetch.identity_cache') do |payload|
77
+ value = ActiveSupport::Notifications.instrument("cache_fetch.identity_cache") do |payload|
77
78
  payload[:resolve_miss_time] = 0.0
78
79
 
79
80
  value = fetch_memoized(key) do
80
81
  memo_misses = 1
81
- @cache_fetcher.fetch(key) do
82
+ @cache_fetcher.fetch(key, **cache_fetcher_options) do
82
83
  cache_misses = 1
83
- instrument_duration(payload, :resolve_miss_time) do
84
- yield
85
- end
84
+ instrument_duration(payload, :resolve_miss_time, &block)
86
85
  end
87
86
  end
88
87
  set_instrumentation_payload(payload, num_keys: 1, memo_misses: memo_misses, cache_misses: cache_misses)
@@ -93,7 +92,7 @@ module IdentityCache
93
92
  IdentityCache.logger.debug { "[IdentityCache] cache miss for #{key}" }
94
93
  else
95
94
  IdentityCache.logger.debug do
96
- "[IdentityCache] #{memo_misses > 0 ? '(cache_backend)' : '(memoized)'} cache hit for #{key}"
95
+ "[IdentityCache] #{memo_misses > 0 ? "(cache_backend)" : "(memoized)"} cache hit for #{key}"
97
96
  end
98
97
  end
99
98
 
@@ -104,7 +103,7 @@ module IdentityCache
104
103
  memo_miss_keys = EMPTY_ARRAY
105
104
  cache_miss_keys = EMPTY_ARRAY
106
105
 
107
- result = ActiveSupport::Notifications.instrument('cache_fetch_multi.identity_cache') do |payload|
106
+ result = ActiveSupport::Notifications.instrument("cache_fetch_multi.identity_cache") do |payload|
108
107
  payload[:resolve_miss_time] = 0.0
109
108
 
110
109
  result = fetch_multi_memoized(keys) do |non_memoized_keys|
@@ -132,7 +131,7 @@ module IdentityCache
132
131
  end
133
132
 
134
133
  def clear
135
- ActiveSupport::Notifications.instrument('cache_clear.identity_cache') do
134
+ ActiveSupport::Notifications.instrument("cache_clear.identity_cache") do
136
135
  clear_memoization
137
136
  @cache_fetcher.clear
138
137
  end
@@ -155,6 +154,7 @@ module IdentityCache
155
154
  if memoized_key_values.key?(key)
156
155
  return memoized_key_values[key]
157
156
  end
157
+
158
158
  memoized_key_values[key] = yield
159
159
  end
160
160
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  module ParentModelExpiration # :nodoc:
4
5
  extend ActiveSupport::Concern
@@ -22,6 +23,7 @@ module IdentityCache
22
23
 
23
24
  def install_pending_parent_expiry_hooks(model)
24
25
  return if lazy_hooks.empty?
26
+
25
27
  name = model.name.demodulize
26
28
  if (hooks = lazy_hooks.delete(name))
27
29
  hooks.each(&:install)
@@ -85,7 +87,7 @@ module IdentityCache
85
87
 
86
88
  cached_associations.each do |parent_class, only_on_foreign_key_change|
87
89
  if new_parent&.is_a?(parent_class) &&
88
- should_expire_identity_cache_parent?(foreign_key, only_on_foreign_key_change)
90
+ should_expire_identity_cache_parent?(foreign_key, only_on_foreign_key_change)
89
91
  add_record_to_cache_expiry_set(parents_to_expire, new_parent)
90
92
  end
91
93
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  module QueryAPI
4
5
  extend ActiveSupport::Concern
@@ -68,6 +69,7 @@ module IdentityCache
68
69
  def setup_embedded_associations_on_miss(records,
69
70
  readonly: IdentityCache.fetch_read_only_records && should_use_cache?)
70
71
  return if records.empty?
72
+
71
73
  records.each(&:readonly!) if readonly
72
74
  each_id_embedded_association do |cached_association|
73
75
  preload_id_embedded_association(records, cached_association)
@@ -86,6 +88,7 @@ module IdentityCache
86
88
  association.reset
87
89
  # reset inverse associations
88
90
  next unless target && association_reflection.has_inverse?
91
+
89
92
  inverse_name = association_reflection.inverse_of.name
90
93
  if target.is_a?(Array)
91
94
  target.each { |child_record| child_record.association(inverse_name).reset }
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  class Railtie < Rails::Railtie
4
5
  initializer "identity_cache.setup" do |app|
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  module ShouldUseCache
4
5
  extend ActiveSupport::Concern
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
- VERSION = "1.1.0"
4
+ VERSION = "1.2.0"
4
5
  CACHE_VERSION = 8
5
6
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  module WithPrimaryIndex
4
5
  extend ActiveSupport::Concern
@@ -57,7 +58,7 @@ module IdentityCache
57
58
  cache_attribute_by_alias(attribute_proc, alias_name: :id, by: fields, unique: unique)
58
59
 
59
60
  field_list = fields.join("_and_")
60
- arg_list = (0...fields.size).collect { |i| "arg#{i}" }.join(',')
61
+ arg_list = (0...fields.size).collect { |i| "arg#{i}" }.join(",")
61
62
 
62
63
  if unique
63
64
  instance_eval(<<-CODE, __FILE__, __LINE__ + 1)
@@ -97,21 +98,47 @@ module IdentityCache
97
98
  !!fetch_by_id(id)
98
99
  end
99
100
 
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)
101
+ # Fetch the record by its primary key from the cache or read from
102
+ # the database and fill the cache on a cache miss. This behaves like
103
+ # `where(id: id).readonly.first` being called on the model.
104
+ #
105
+ # @param id Primary key value for the record to fetch.
106
+ # @param includes [Hash|Array|Symbol] Cached associations to prefetch from
107
+ # the cache on the returned record
108
+ # @param fill_lock_duration [Float] If provided, take a fill lock around cache fills
109
+ # and wait for this duration for cache to be filled when reading a lock provided
110
+ # by another client. Defaults to not setting the fill lock and trying to fill the
111
+ # cache from the database regardless of the presence of another client's fill lock.
112
+ # Set this to just above the typical amount of time it takes to do a cache fill.
113
+ # @param lock_wait_tries [Integer] Only applicable if fill_lock_duration is provided,
114
+ # in which case it specifies the number of times to do a lock wait. After the first
115
+ # lock wait it will try to take the lock, so will only do following lock waits due
116
+ # to another client taking the lock first. If another lock wait would be needed after
117
+ # reaching the limit, then a `LockWaitTimeout` exception is raised. Default is 2. Use
118
+ # this to control the maximum total lock wait duration
119
+ # (`lock_wait_tries * fill_lock_duration`).
120
+ # @raise [LockWaitTimeout] Timeout after waiting `lock_wait_tries * fill_lock_duration`
121
+ # seconds for `lock_wait_tries` other clients to fill the cache.
122
+ # @return [self|nil] An instance of this model for the record with the specified id or
123
+ # `nil` if no record with this `id` exists in the database
124
+ def fetch_by_id(id, includes: nil, **cache_fetcher_options)
103
125
  ensure_base_model
104
126
  raise_if_scoped
105
- record = cached_primary_index.fetch(id)
127
+ record = cached_primary_index.fetch(id, cache_fetcher_options)
106
128
  prefetch_associations(includes, [record]) if record && includes
107
129
  record
108
130
  end
109
131
 
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(
132
+ # Fetch the record by its primary key from the cache or read from
133
+ # the database and fill the cache on a cache miss. This behaves like
134
+ # `readonly.find(id)` being called on the model.
135
+ #
136
+ # @param (see #fetch_by_id)
137
+ # @raise (see #fetch_by_id)
138
+ # @raise [ActiveRecord::RecordNotFound] if the record isn't found
139
+ # @return [self] An instance of this model for the record with the specified id
140
+ def fetch(id, **options)
141
+ fetch_by_id(id, **options) || raise(
115
142
  IdentityCache::RecordNotFound, "Couldn't find #{name} with ID=#{id}"
116
143
  )
117
144
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module IdentityCache
3
4
  module WithoutPrimaryIndex
4
5
  extend ActiveSupport::Concern
@@ -12,9 +13,12 @@ module IdentityCache
12
13
  include IdentityCache::ShouldUseCache
13
14
  include ParentModelExpiration
14
15
 
15
- def self.append_features(base) #:nodoc:
16
- raise AlreadyIncludedError if base.include?(WithoutPrimaryIndex)
17
- super
16
+ class << self
17
+ def append_features(base) # :nodoc:
18
+ raise AlreadyIncludedError if base.include?(WithoutPrimaryIndex)
19
+
20
+ super
21
+ end
18
22
  end
19
23
 
20
24
  included do
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
- require 'active_record'
3
- require 'active_support/core_ext/module/attribute_accessors'
4
- require 'ar_transaction_changes'
2
+
3
+ require "active_record"
4
+ require "active_support/core_ext/module/attribute_accessors"
5
+ require "ar_transaction_changes"
5
6
 
6
7
  require "identity_cache/version"
7
8
  require "identity_cache/record_not_found"
@@ -27,24 +28,24 @@ require "identity_cache/cached/reference/association"
27
28
  require "identity_cache/cached/reference/has_one"
28
29
  require "identity_cache/cached/reference/has_many"
29
30
  require "identity_cache/expiry_hook"
30
- require 'identity_cache/memoized_cache_proxy'
31
- require 'identity_cache/belongs_to_caching'
32
- require 'identity_cache/cache_key_generation'
33
- require 'identity_cache/configuration_dsl'
34
- require 'identity_cache/should_use_cache'
35
- require 'identity_cache/parent_model_expiration'
36
- require 'identity_cache/query_api'
31
+ require "identity_cache/memoized_cache_proxy"
32
+ require "identity_cache/belongs_to_caching"
33
+ require "identity_cache/cache_key_generation"
34
+ require "identity_cache/configuration_dsl"
35
+ require "identity_cache/should_use_cache"
36
+ require "identity_cache/parent_model_expiration"
37
+ require "identity_cache/query_api"
37
38
  require "identity_cache/cache_hash"
38
39
  require "identity_cache/cache_invalidation"
39
40
  require "identity_cache/cache_fetcher"
40
41
  require "identity_cache/fallback_fetcher"
41
- require 'identity_cache/without_primary_index'
42
- require 'identity_cache/with_primary_index'
42
+ require "identity_cache/without_primary_index"
43
+ require "identity_cache/with_primary_index"
43
44
 
44
45
  module IdentityCache
45
46
  extend ActiveSupport::Concern
46
47
 
47
- autoload :MemCacheStoreCAS, 'identity_cache/mem_cache_store_cas'
48
+ autoload :MemCacheStoreCAS, "identity_cache/mem_cache_store_cas"
48
49
 
49
50
  include WithPrimaryIndex
50
51
 
@@ -65,23 +66,26 @@ module IdentityCache
65
66
 
66
67
  class DerivedModelError < StandardError; end
67
68
 
69
+ class LockWaitTimeout < StandardError; end
70
+
68
71
  mattr_accessor :cache_namespace
69
72
  self.cache_namespace = "IDC:#{CACHE_VERSION}:"
70
73
 
71
74
  # Fetched records are not read-only and this could sometimes prevent IDC from
72
75
  # reflecting what's truly in the database when fetch_read_only_records is false.
73
76
  # When set to true, it will only return read-only records when cache is used.
74
- mattr_accessor :fetch_read_only_records
75
- self.fetch_read_only_records = true
77
+ @fetch_read_only_records = true
76
78
 
77
79
  class << self
78
80
  include IdentityCache::CacheHash
79
81
 
82
+ attr_writer :fetch_read_only_records
80
83
  attr_accessor :readonly
81
84
  attr_writer :logger
82
85
 
83
- def append_features(base) #:nodoc:
86
+ def append_features(base) # :nodoc:
84
87
  raise AlreadyIncludedError if base.include?(IdentityCache)
88
+
85
89
  super
86
90
  end
87
91
 
@@ -141,10 +145,13 @@ module IdentityCache
141
145
  #
142
146
  # == Parameters
143
147
  # +key+ A cache key string
148
+ # +cache_fetcher_options+ A hash of options to pass to the cache backend
144
149
  #
145
- def fetch(key)
150
+ def fetch(key, cache_fetcher_options = {})
146
151
  if should_use_cache?
147
- unmap_cached_nil_for(cache.fetch(key) { map_cached_nil_for(yield) })
152
+ unmap_cached_nil_for(cache.fetch(key, cache_fetcher_options) do
153
+ map_cached_nil_for(yield)
154
+ end)
148
155
  else
149
156
  yield
150
157
  end
@@ -185,11 +192,18 @@ module IdentityCache
185
192
  end
186
193
 
187
194
  def with_fetch_read_only_records(value = true)
188
- old_value = fetch_read_only_records
189
- self.fetch_read_only_records = value
195
+ old_value = Thread.current[:identity_cache_fetch_read_only_records]
196
+ Thread.current[:identity_cache_fetch_read_only_records] = value
190
197
  yield
191
198
  ensure
192
- self.fetch_read_only_records = old_value
199
+ Thread.current[:identity_cache_fetch_read_only_records] = old_value
200
+ end
201
+
202
+ def fetch_read_only_records
203
+ v = Thread.current[:identity_cache_fetch_read_only_records]
204
+ return v unless v.nil?
205
+
206
+ @fetch_read_only_records
193
207
  end
194
208
 
195
209
  def eager_load!
@@ -198,12 +212,12 @@ module IdentityCache
198
212
 
199
213
  private
200
214
 
201
- def fetch_in_batches(keys)
215
+ def fetch_in_batches(keys, &block)
202
216
  keys.each_slice(BATCH_SIZE).each_with_object({}) do |slice, result|
203
- result.merge!(cache.fetch_multi(*slice) { |missed_keys| yield missed_keys })
217
+ result.merge!(cache.fetch_multi(*slice, &block))
204
218
  end
205
219
  end
206
220
  end
207
221
  end
208
222
 
209
- require 'identity_cache/railtie' if defined?(Rails)
223
+ require "identity_cache/railtie" if defined?(Rails)
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  $LOAD_PATH.unshift(File.expand_path("../../lib", __FILE__))
3
- require 'active_record'
4
- require 'active_support/core_ext'
5
- require 'active_support/cache'
6
- require 'identity_cache'
7
- require 'memcached_store'
8
- require 'active_support/cache/memcached_store'
4
+ require "active_record"
5
+ require "active_support/core_ext"
6
+ require "active_support/cache"
7
+ require "identity_cache"
8
+ require "memcached_store"
9
+ require "active_support/cache/memcached_store"
9
10
 
10
- require File.dirname(__FILE__) + '/../test/helpers/active_record_objects'
11
- require File.dirname(__FILE__) + '/../test/helpers/database_connection'
12
- require File.dirname(__FILE__) + '/../test/helpers/cache_connection'
11
+ require File.dirname(__FILE__) + "/../test/helpers/active_record_objects"
12
+ require File.dirname(__FILE__) + "/../test/helpers/database_connection"
13
+ require File.dirname(__FILE__) + "/../test/helpers/cache_connection"
13
14
 
14
15
  IdentityCache.logger = Logger.new(nil)
15
16
  CacheConnection.setup
@@ -31,6 +32,7 @@ def create_database(count)
31
32
  helper.setup_models
32
33
 
33
34
  return if database_ready(count)
35
+
34
36
  puts "Database not ready for performance testing, generating records"
35
37
 
36
38
  DatabaseConnection.drop_tables
@@ -38,6 +40,7 @@ def create_database(count)
38
40
  existing = Item.all
39
41
  (1..count).to_a.each do |i|
40
42
  next if existing.any? { |e| e.id == i }
43
+
41
44
  a = Item.new
42
45
  a.id = i
43
46
  a.associated = AssociatedRecord.new(name: "Associated for #{i}")
data/performance/cpu.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
- require 'rubygems'
3
- require 'benchmark'
4
2
 
5
- require_relative 'cache_runner'
3
+ require "rubygems"
4
+ require "benchmark"
5
+
6
+ require_relative "cache_runner"
6
7
 
7
8
  RUNS = 400
8
9
 
@@ -32,9 +33,9 @@ def bmbm(runners)
32
33
  label_width = runners.map { |r| r.name.size }.max + 2
33
34
  width = label_width + Benchmark::CAPTION.size
34
35
 
35
- puts 'Rehearsal: '.ljust(width, '-')
36
+ puts "Rehearsal: ".ljust(width, "-")
36
37
  benchmark(runners, label_width)
37
- puts '-' * width
38
+ puts "-" * width
38
39
 
39
40
  benchmark(runners, label_width)
40
41
  end
@@ -1,15 +1,16 @@
1
1
  # frozen_string_literal: true
2
- require 'rubygems'
3
- require 'benchmark'
4
- require 'ruby-prof'
5
2
 
6
- require_relative 'cache_runner'
3
+ require "rubygems"
4
+ require "benchmark"
5
+ require "ruby-prof"
6
+
7
+ require_relative "cache_runner"
7
8
 
8
9
  RUNS = 1000
9
10
  RubyProf.measure_mode = RubyProf::CPU_TIME
10
11
 
11
12
  EXTERNALS = { "Memcache" => ["MemCache#set", "MemCache#get"],
12
- "Database" => ["Mysql2::Client#query"] }
13
+ "Database" => ["Mysql2::Client#query"], }
13
14
 
14
15
  def run(obj)
15
16
  obj.prepare
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
- require 'rubygems'
3
- require 'benchmark'
4
- require 'stackprof'
5
2
 
6
- require_relative 'cache_runner'
3
+ require "rubygems"
4
+ require "benchmark"
5
+ require "stackprof"
6
+
7
+ require_relative "cache_runner"
7
8
 
8
9
  RUNS = 1000
9
10
 
@@ -22,9 +23,9 @@ end
22
23
 
23
24
  create_database(RUNS)
24
25
 
25
- if (runner_name = ENV['RUNNER'])
26
+ if (runner_name = ENV["RUNNER"])
26
27
  if (runner = CACHE_RUNNERS.find { |r| r.name == runner_name })
27
- run(runner.new(RUNS), filename: ENV['FILENAME'])
28
+ run(runner.new(RUNS), filename: ENV["FILENAME"])
28
29
  else
29
30
  puts "Couldn't find cache runner #{runner_name.inspect}"
30
31
  exit(1)