kasket 4.8.0 → 4.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5cec0e5e944a74b977fd8e8113983160e1a5075eade70a499e6b16863abfde6
4
- data.tar.gz: d9ee5a1d6a974e998191ad656b4b962b5a7ea74e0327be3944813790bf6e7e8c
3
+ metadata.gz: e1399453146b7dcf0974eb42a7b80375291b2978415269d686ff66ccb77b9f53
4
+ data.tar.gz: 4649d5f06595e558f859472439733208e62229841901bf9dc81b602c3f78e07e
5
5
  SHA512:
6
- metadata.gz: 9aca01c0f69b403d2476b5db05b610604899f2a38f450b0c29d8f19b60f5f2e3e67777c172690672ae83a1a4ce14e316c85175989d5dd4df826afdbf6b8e530c
7
- data.tar.gz: 1645f52ca823c5c628d9fa5c1aba45393feffc9ac3f0c0e70e1552582bd55de79df20f8870f72deca67d8e0faae036d5fc5d1fa67b7be80dcf836d86808b7c68
6
+ metadata.gz: 7a6eeea3f1cdfe9bb349379cb07f4d13a21bfa0867ed09e9795746d91f74a69349ee15eb83d76e6f4776a717d8d4f2b8ce1479d41a095ac2e275502e3b54c99c
7
+ data.tar.gz: fd34ac51846f1748a47cf0de7b2c5f27ef843abe93429285e3830a8a8c3afb53822f7eab19452af3df5c99483323e1c0d9fd2a727ddda535626e58408a5a28e1
data/lib/kasket.rb CHANGED
@@ -17,8 +17,8 @@ module Kasket
17
17
 
18
18
  CONFIGURATION = { # rubocop:disable Style/MutableConstant
19
19
  max_collection_size: 100,
20
- write_through: false,
21
- default_expires_in: nil
20
+ write_through: false,
21
+ default_expires_in: nil
22
22
  }
23
23
 
24
24
  module_function
@@ -33,8 +33,8 @@ module Kasket
33
33
  ActiveRecord::Base.extend(Kasket::ConfigurationMixin)
34
34
 
35
35
  if defined?(ActiveRecord::Relation)
36
- ActiveRecord::Relation.send(:include, Kasket::RelationMixin)
37
- Arel::SelectManager.send(:include, Kasket::SelectManagerMixin)
36
+ ActiveRecord::Relation.include Kasket::RelationMixin
37
+ Arel::SelectManager.include Kasket::SelectManagerMixin
38
38
  end
39
39
  end
40
40
 
@@ -42,10 +42,15 @@ module Kasket
42
42
  @cache_store = ActiveSupport::Cache.lookup_store(options)
43
43
  end
44
44
 
45
- def self.cache
45
+ def self.cache_store
46
46
  @cache_store ||= Rails.cache
47
47
  end
48
48
 
49
+ # Alias cache_store to cache
50
+ class << self
51
+ alias_method :cache, :cache_store
52
+ end
53
+
49
54
  # Keys are the records being saved.
50
55
  # Values are either the saved record, or nil if the record has been destroyed.
51
56
  def self.pending_records
@@ -6,8 +6,8 @@ module Kasket
6
6
  # SELECT * FROM `users` WHERE (`users`.`id` = 2) LIMIT 1
7
7
  # 'SELECT * FROM \'posts\' WHERE (\'posts\'.\'id\' = 574019247) '
8
8
 
9
- AND = /\s+AND\s+/i
10
- VALUE = /'?(\d+|\?|(?:(?:[^']|''|\\')*))'?/ # Matches: 123, ?, '123', '12''3'
9
+ AND = /\s+AND\s+/i.freeze
10
+ VALUE = /'?(\d+|\?|(?:(?:[^']|''|\\')*))'?/.freeze # Matches: 123, ?, '123', '12''3'
11
11
 
12
12
  def initialize(model_class)
13
13
  @model_class = model_class
@@ -8,6 +8,7 @@ module Kasket
8
8
  end
9
9
  end
10
10
 
11
+ # *args can be replaced with (sql, *args) once we stop supporting Rails < 5.2
11
12
  def find_by_sql_with_kasket(*args)
12
13
  sql = args[0]
13
14
 
@@ -32,11 +33,27 @@ module Kasket
32
33
  find_by_sql_with_kasket_on_id_array(query[:key])
33
34
  else
34
35
  if value = Kasket.cache.read(query[:key])
35
- if value.is_a?(Array)
36
+ # Identified a specific edge case where memcached server returns 0x00 binary protocol response with no data
37
+ # when the node is being rebooted which causes the Dalli memcached client to return a TrueClass object instead of nil
38
+ # see: https://github.com/petergoldstein/dalli/blob/31dabf19d3dd94b348a00a59fe5a7b8fa80ce3ad/lib/dalli/server.rb#L520
39
+ # and: https://github.com/petergoldstein/dalli/issues/390
40
+ #
41
+ # The code in this first condition of TrueClass === true will
42
+ # skip the kasket cache for these specific objects and go directly to SQL for retrieval.
43
+ result_set = if value.is_a?(TrueClass)
44
+ find_by_sql_without_kasket(*args)
45
+ elsif value.is_a?(Array)
36
46
  filter_pending_records(find_by_sql_with_kasket_on_id_array(value))
37
47
  else
38
48
  filter_pending_records(Array.wrap(value).collect { |record| instantiate(record.dup) })
39
49
  end
50
+
51
+ payload = {
52
+ record_count: result_set.length,
53
+ class_name: to_s
54
+ }
55
+
56
+ ActiveSupport::Notifications.instrument('instantiation.active_record', payload) { result_set }
40
57
  else
41
58
  store_in_kasket(query[:key], find_by_sql_without_kasket(*args))
42
59
  end
@@ -80,7 +97,7 @@ module Kasket
80
97
  if records.size == 1
81
98
  records.first.store_in_kasket(key)
82
99
  elsif records.empty?
83
- ActiveRecord::Base.logger.info("[KASKET] would have stored an empty resultset") if ActiveRecord::Base.logger
100
+ ActiveRecord::Base.logger.debug("[KASKET] would have stored an empty resultset") if ActiveRecord::Base.logger
84
101
  elsif records.size <= Kasket::CONFIGURATION[:max_collection_size]
85
102
  if records.all?(&:kasket_cacheable?)
86
103
  instance_keys = records.map(&:store_in_kasket)
@@ -1,16 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
  module Kasket
3
3
  module RelationMixin
4
+ # binds can be removed when support for Rails < 5 is removed
4
5
  def to_kasket_query(binds = nil)
5
6
  if arel.is_a?(Arel::SelectManager)
6
7
  if ActiveRecord::VERSION::MAJOR < 5
7
8
  arel.to_kasket_query(klass, (binds || bind_values))
8
- else
9
+ elsif ActiveRecord::VERSION::STRING < '5.2'
9
10
  arel.to_kasket_query(klass, (@values[:where].to_h.values + Array(@values[:limit])))
11
+ else
12
+ arel.to_kasket_query(klass)
10
13
  end
11
14
  end
12
15
  rescue TypeError # unsupported object in ast
13
- return nil
16
+ nil
14
17
  end
15
18
  end
16
19
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module Kasket
3
3
  module SelectManagerMixin
4
+ # binds can be removed once we stop supporting Rails < 5.2
4
5
  def to_kasket_query(klass, binds = [])
5
6
  begin
6
7
  query = Kasket::Visitor.new(klass, binds).accept(ast)
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Kasket
3
- VERSION = '4.8.0'
3
+ VERSION = '4.9.0'
4
4
  class Version
5
5
  MAJOR = Kasket::VERSION.split('.')[0]
6
6
  MINOR = Kasket::VERSION.split('.')[1]
@@ -3,6 +3,7 @@ require 'arel'
3
3
 
4
4
  module Kasket
5
5
  class Visitor < Arel::Visitors::Visitor
6
+ # binds can be removed once we stop supporting Rails < 5.2
6
7
  def initialize(model_class, binds)
7
8
  @model_class = model_class
8
9
  @binds = binds.dup
@@ -75,6 +76,7 @@ module Kasket
75
76
  def visit_Arel_Nodes_JoinSource(node, *_)
76
77
  return :unsupported if !node.left || node.right.any?
77
78
  return :unsupported unless node.left.is_a?(Arel::Table)
79
+
78
80
  visit(node.left)
79
81
  end
80
82
 
@@ -85,6 +87,7 @@ module Kasket
85
87
  def visit_Arel_Nodes_And(node, *_)
86
88
  attributes = node.children.map { |child| visit(child) }
87
89
  return :unsupported if attributes.include?(:unsupported)
90
+
88
91
  attributes.sort! { |pair1, pair2| pair1[0].to_s <=> pair2[0].to_s }
89
92
  { attributes: attributes }
90
93
  end
@@ -112,8 +115,12 @@ module Kasket
112
115
  end
113
116
 
114
117
  def literal(node, *_)
115
- if node == '?'
116
- @binds.shift.last.to_s
118
+ if ActiveRecord::VERSION::STRING < '5.2'
119
+ if node == '?'
120
+ @binds.shift.last.to_s
121
+ else
122
+ node.to_s
123
+ end
117
124
  else
118
125
  node.to_s
119
126
  end
@@ -135,11 +142,13 @@ module Kasket
135
142
  node.map {|value| visit(value) }
136
143
  end
137
144
 
138
- def visit_Arel_Nodes_Casted(node, *_)
139
- case node.val
140
- when nil then nil
141
- when String then node.val
142
- else quoted(node.val)
145
+ if ActiveRecord::VERSION::STRING < '5.2'
146
+ def visit_Arel_Nodes_Casted(node, *_)
147
+ case node.val
148
+ when nil then nil
149
+ when String then node.val
150
+ else quoted(node.val)
151
+ end
143
152
  end
144
153
  end
145
154
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kasket
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.0
4
+ version: 4.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mick Staugaard
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-08-26 00:00:00.000000000 Z
12
+ date: 2021-07-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -32,7 +32,7 @@ dependencies:
32
32
  - !ruby/object:Gem::Version
33
33
  version: '6.1'
34
34
  - !ruby/object:Gem::Dependency
35
- name: rake
35
+ name: bump
36
36
  requirement: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
@@ -60,7 +60,7 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: mocha
63
+ name: minitest
64
64
  requirement: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - ">="
@@ -74,7 +74,7 @@ dependencies:
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  - !ruby/object:Gem::Dependency
77
- name: wwtd
77
+ name: minitest-rg
78
78
  requirement: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - ">="
@@ -88,7 +88,7 @@ dependencies:
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  - !ruby/object:Gem::Dependency
91
- name: bump
91
+ name: mocha
92
92
  requirement: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - ">="
@@ -102,7 +102,7 @@ dependencies:
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  - !ruby/object:Gem::Dependency
105
- name: minitest
105
+ name: rake
106
106
  requirement: !ruby/object:Gem::Requirement
107
107
  requirements:
108
108
  - - ">="
@@ -116,7 +116,7 @@ dependencies:
116
116
  - !ruby/object:Gem::Version
117
117
  version: '0'
118
118
  - !ruby/object:Gem::Dependency
119
- name: minitest-rg
119
+ name: timecop
120
120
  requirement: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
@@ -130,7 +130,7 @@ dependencies:
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  - !ruby/object:Gem::Dependency
133
- name: timecop
133
+ name: wwtd
134
134
  requirement: !ruby/object:Gem::Requirement
135
135
  requirements:
136
136
  - - ">="
@@ -173,14 +173,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
173
173
  requirements:
174
174
  - - ">="
175
175
  - !ruby/object:Gem::Version
176
- version: 2.3.0
176
+ version: 2.5.0
177
177
  required_rubygems_version: !ruby/object:Gem::Requirement
178
178
  requirements:
179
179
  - - ">="
180
180
  - !ruby/object:Gem::Version
181
181
  version: '0'
182
182
  requirements: []
183
- rubygems_version: 3.1.4
183
+ rubygems_version: 3.2.22
184
184
  signing_key:
185
185
  specification_version: 4
186
186
  summary: A write back caching layer on active record