kasket 4.10.4 → 4.12.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 +4 -4
- data/README.md +15 -1
- data/lib/kasket/configuration_mixin.rb +2 -6
- data/lib/kasket/read_mixin.rb +8 -15
- data/lib/kasket/relation_mixin.rb +2 -5
- data/lib/kasket/version.rb +1 -1
- data/lib/kasket/visitor.rb +24 -13
- data/lib/kasket/write_mixin.rb +14 -31
- data/lib/kasket.rb +2 -5
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 52a098184223192a1d4a6cd6a92363dd5f9324b4d2c56da1fa33769402e0c602
|
4
|
+
data.tar.gz: 4fca1aba72b41281fb71f91a61ba18d96edb93cb60ff94924c63fe7353bd96d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4aa6be9f52ab44578929a3e66fa2ddfb71a6d935e00d13e80258fe4ec413ac69cae42666512e3711c189edf03e6e011ecd64a13d9a210449edc292aeea098680
|
7
|
+
data.tar.gz: 0131bde86df784810b892da100e6e5c26e40620071c6169def6f7cbb7f176775ed981c7174c2be247a1c188053b755dab6469d9cd39e51104921f57d73721f72
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Kasket
|
2
2
|
|
3
3
|
### Puts a cap on your queries
|
4
|
-
A caching layer for ActiveRecord
|
4
|
+
A caching layer for ActiveRecord.
|
5
5
|
|
6
6
|
Developed and used by [Zendesk](http://zendesk.com).
|
7
7
|
|
@@ -137,6 +137,20 @@ Absolutely, but Cache Money does so much more.
|
|
137
137
|
* The Cache Money code is overly complex.
|
138
138
|
* Cache Money seems abandoned.
|
139
139
|
|
140
|
+
## Development
|
141
|
+
|
142
|
+
Run the tests with:
|
143
|
+
|
144
|
+
```
|
145
|
+
$ rake test
|
146
|
+
```
|
147
|
+
|
148
|
+
Access a dev console running on the local test DB:
|
149
|
+
|
150
|
+
```
|
151
|
+
$ bin/console
|
152
|
+
```
|
153
|
+
|
140
154
|
## Note on Patches/Pull Requests
|
141
155
|
|
142
156
|
* Fork the project.
|
@@ -101,12 +101,8 @@ module Kasket
|
|
101
101
|
def kasket_quoted_value_for_column(value, column)
|
102
102
|
if column
|
103
103
|
conn = connection
|
104
|
-
|
105
|
-
|
106
|
-
when 3 then column.type_cast(value)
|
107
|
-
when 4 then column.type_cast_for_database(value)
|
108
|
-
else conn.type_cast_from_column(column, value)
|
109
|
-
end
|
104
|
+
type = conn.lookup_cast_type_from_column(column)
|
105
|
+
casted_value = conn.type_cast(type.serialize(value))
|
110
106
|
conn.quote(casted_value).downcase
|
111
107
|
else
|
112
108
|
value.to_s
|
data/lib/kasket/read_mixin.rb
CHANGED
@@ -8,20 +8,13 @@ module Kasket
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
|
12
|
-
def find_by_sql_with_kasket(*args)
|
13
|
-
sql = args[0]
|
14
|
-
|
11
|
+
def find_by_sql_with_kasket(sql, binds = [], *restargs, **kwargs, &blk)
|
15
12
|
if use_kasket?
|
16
13
|
query = if sql.respond_to?(:to_kasket_query)
|
17
|
-
if ActiveRecord::VERSION::
|
18
|
-
sql.to_kasket_query(self,
|
14
|
+
if ActiveRecord::VERSION::STRING < '5.2'
|
15
|
+
sql.to_kasket_query(self, binds.map(&:value_for_database))
|
19
16
|
else
|
20
|
-
|
21
|
-
sql.to_kasket_query(self, args[1].map(&:value_for_database))
|
22
|
-
else
|
23
|
-
sql.to_kasket_query(self)
|
24
|
-
end
|
17
|
+
sql.to_kasket_query(self)
|
25
18
|
end
|
26
19
|
else
|
27
20
|
kasket_parser.parse(sanitize_sql(sql))
|
@@ -30,7 +23,7 @@ module Kasket
|
|
30
23
|
|
31
24
|
if query && has_kasket_index_on?(query[:index])
|
32
25
|
if query[:key].is_a?(Array)
|
33
|
-
find_by_sql_with_kasket_on_id_array(query[:key])
|
26
|
+
filter_pending_records(find_by_sql_with_kasket_on_id_array(query[:key]))
|
34
27
|
else
|
35
28
|
if value = Kasket.cache.read(query[:key])
|
36
29
|
# Identified a specific edge case where memcached server returns 0x00 binary protocol response with no data
|
@@ -41,7 +34,7 @@ module Kasket
|
|
41
34
|
# The code in this first condition of TrueClass === true will
|
42
35
|
# skip the kasket cache for these specific objects and go directly to SQL for retrieval.
|
43
36
|
result_set = if value.is_a?(TrueClass)
|
44
|
-
find_by_sql_without_kasket(*
|
37
|
+
find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk)
|
45
38
|
elsif value.is_a?(Array)
|
46
39
|
filter_pending_records(find_by_sql_with_kasket_on_id_array(value))
|
47
40
|
else
|
@@ -55,11 +48,11 @@ module Kasket
|
|
55
48
|
|
56
49
|
ActiveSupport::Notifications.instrument('instantiation.active_record', payload) { result_set }
|
57
50
|
else
|
58
|
-
store_in_kasket(query[:key], find_by_sql_without_kasket(*
|
51
|
+
store_in_kasket(query[:key], find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk))
|
59
52
|
end
|
60
53
|
end
|
61
54
|
else
|
62
|
-
find_by_sql_without_kasket(*
|
55
|
+
find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk)
|
63
56
|
end
|
64
57
|
end
|
65
58
|
|
@@ -1,12 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Kasket
|
3
3
|
module RelationMixin
|
4
|
-
|
5
|
-
def to_kasket_query(binds = nil)
|
4
|
+
def to_kasket_query
|
6
5
|
if arel.is_a?(Arel::SelectManager)
|
7
|
-
if ActiveRecord::VERSION::
|
8
|
-
arel.to_kasket_query(klass, (binds || bind_values))
|
9
|
-
elsif ActiveRecord::VERSION::STRING < '5.2'
|
6
|
+
if ActiveRecord::VERSION::STRING < '5.2'
|
10
7
|
arel.to_kasket_query(klass, (@values[:where].to_h.values + Array(@values[:limit])))
|
11
8
|
else
|
12
9
|
arel.to_kasket_query(klass)
|
data/lib/kasket/version.rb
CHANGED
data/lib/kasket/visitor.rb
CHANGED
@@ -49,7 +49,7 @@ module Kasket
|
|
49
49
|
|
50
50
|
def visit_Arel_Nodes_SelectCore(node, *_)
|
51
51
|
return :unsupported if node.groups.any?
|
52
|
-
return :unsupported if
|
52
|
+
return :unsupported if node.havings.present?
|
53
53
|
return :unsupported if node.set_quantifier
|
54
54
|
return :unsupported if !node.source || node.source.empty?
|
55
55
|
return :unsupported if node.projections.empty?
|
@@ -65,6 +65,14 @@ module Kasket
|
|
65
65
|
return unless (column_names - projection_names).empty?
|
66
66
|
end
|
67
67
|
|
68
|
+
# un-optimize AR 6.1 by adding a redundant And node to hit visitor below
|
69
|
+
if ActiveRecord::VERSION::STRING.start_with? "6.1"
|
70
|
+
if node.wheres.size == 1
|
71
|
+
n = node.wheres[0]
|
72
|
+
node.wheres[0] = Arel::Nodes::And.new([n]) unless n.is_a?(Arel::Nodes::And)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
68
76
|
parts = [visit(node.source)]
|
69
77
|
|
70
78
|
parts += node.wheres.map {|where| visit(where) }
|
@@ -73,11 +81,7 @@ module Kasket
|
|
73
81
|
end
|
74
82
|
|
75
83
|
def visit_Arel_Nodes_Limit(node, *_)
|
76
|
-
|
77
|
-
{ limit: node.value.to_i }
|
78
|
-
else
|
79
|
-
{ limit: visit(node.value).to_i }
|
80
|
-
end
|
84
|
+
{ limit: visit(node.value).to_i }
|
81
85
|
end
|
82
86
|
|
83
87
|
def visit_Arel_Nodes_JoinSource(node, *_)
|
@@ -106,6 +110,8 @@ module Kasket
|
|
106
110
|
[left, visit(node.right)]
|
107
111
|
end
|
108
112
|
|
113
|
+
alias_method :visit_Arel_Nodes_HomogeneousIn, :visit_Arel_Nodes_In
|
114
|
+
|
109
115
|
def visit_Arel_Nodes_Equality(node, *_)
|
110
116
|
right =
|
111
117
|
case node.right
|
@@ -134,14 +140,10 @@ module Kasket
|
|
134
140
|
end
|
135
141
|
|
136
142
|
def visit_Arel_Nodes_BindParam(node, *_)
|
137
|
-
if ActiveRecord::VERSION::
|
138
|
-
visit(@binds.shift
|
143
|
+
if ActiveRecord::VERSION::STRING < '5.2'
|
144
|
+
visit(@binds.shift)
|
139
145
|
else
|
140
|
-
|
141
|
-
visit(@binds.shift)
|
142
|
-
else
|
143
|
-
visit(node.value.value) unless node.value.value.nil?
|
144
|
-
end
|
146
|
+
visit(node.value.value) unless node.value.value.nil?
|
145
147
|
end
|
146
148
|
end
|
147
149
|
|
@@ -157,6 +159,15 @@ module Kasket
|
|
157
159
|
else quoted(node.val)
|
158
160
|
end
|
159
161
|
end
|
162
|
+
else # R52: val -> value
|
163
|
+
def visit_Arel_Nodes_Casted(node, *_)
|
164
|
+
v = node.value
|
165
|
+
case v
|
166
|
+
when nil then nil
|
167
|
+
when String then v
|
168
|
+
else quoted(v)
|
169
|
+
end
|
170
|
+
end
|
160
171
|
end
|
161
172
|
|
162
173
|
def visit_TrueClass(_node)
|
data/lib/kasket/write_mixin.rb
CHANGED
@@ -8,14 +8,14 @@ module Kasket
|
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
def update_counters_with_kasket_clearing(*args)
|
11
|
+
def update_counters_with_kasket_clearing(*args, **kwargs)
|
12
12
|
remove_from_kasket(args[0])
|
13
|
-
update_counters_without_kasket_clearing(*args)
|
13
|
+
update_counters_without_kasket_clearing(*args, **kwargs)
|
14
14
|
end
|
15
15
|
|
16
|
-
def transaction_with_kasket_disabled(*args)
|
16
|
+
def transaction_with_kasket_disabled(*args, **kwargs)
|
17
17
|
without_kasket do
|
18
|
-
transaction_without_kasket_disabled(*args) { yield }
|
18
|
+
transaction_without_kasket_disabled(*args, **kwargs) { yield }
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
@@ -41,11 +41,7 @@ module Kasket
|
|
41
41
|
attribute_sets = [attributes]
|
42
42
|
|
43
43
|
previous_changes = options[:previous_changes]
|
44
|
-
previous_changes ||=
|
45
|
-
saved_changes.transform_values(&:first)
|
46
|
-
else
|
47
|
-
previous_changes() # keep parens or rename the local var
|
48
|
-
end
|
44
|
+
previous_changes ||= saved_changes.transform_values(&:first)
|
49
45
|
if previous_changes.present?
|
50
46
|
old_attributes = previous_changes.each_with_object({}) do |(attribute, (old, _)), all|
|
51
47
|
all[attribute.to_s] = old
|
@@ -93,23 +89,14 @@ module Kasket
|
|
93
89
|
super
|
94
90
|
end
|
95
91
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
clear_kasket_indices(previous_changes: previous_changes)
|
101
|
-
result
|
102
|
-
end
|
103
|
-
else
|
104
|
-
def update_columns(new_attributes)
|
105
|
-
previous_attributes = attributes
|
106
|
-
previous_changes = new_attributes.each_with_object({}) do |(k, v), all|
|
107
|
-
all[k] = [previous_attributes[k.to_s], v]
|
108
|
-
end
|
109
|
-
result = super
|
110
|
-
clear_kasket_indices(previous_changes: previous_changes)
|
111
|
-
result
|
92
|
+
def update_columns(new_attributes)
|
93
|
+
previous_attributes = attributes
|
94
|
+
previous_changes = new_attributes.each_with_object({}) do |(k, v), all|
|
95
|
+
all[k] = [previous_attributes[k.to_s], v]
|
112
96
|
end
|
97
|
+
result = super
|
98
|
+
clear_kasket_indices(previous_changes: previous_changes)
|
99
|
+
result
|
113
100
|
end
|
114
101
|
|
115
102
|
def kasket_after_commit_dummy
|
@@ -124,13 +111,13 @@ module Kasket
|
|
124
111
|
Kasket.add_pending_record(self, _destroyed = true)
|
125
112
|
end
|
126
113
|
|
127
|
-
def committed!(*)
|
114
|
+
def committed!(*args, **kwargs)
|
128
115
|
Kasket.clear_pending_records
|
129
116
|
kasket_after_commit if persisted? || destroyed?
|
130
117
|
super
|
131
118
|
end
|
132
119
|
|
133
|
-
def rolledback!(*)
|
120
|
+
def rolledback!(*args, **kwargs)
|
134
121
|
Kasket.clear_pending_records
|
135
122
|
super
|
136
123
|
end
|
@@ -148,10 +135,6 @@ module Kasket
|
|
148
135
|
model_class.after_destroy :kasket_after_destroy
|
149
136
|
model_class.after_commit :kasket_after_commit_dummy
|
150
137
|
|
151
|
-
if ActiveRecord::VERSION::MAJOR == 3 || (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 0)
|
152
|
-
model_class.after_touch :kasket_after_commit
|
153
|
-
end
|
154
|
-
|
155
138
|
class << model_class
|
156
139
|
alias_method :transaction_without_kasket_disabled, :transaction
|
157
140
|
alias_method :transaction, :transaction_with_kasket_disabled
|
data/lib/kasket.rb
CHANGED
@@ -31,11 +31,8 @@ module Kasket
|
|
31
31
|
CONFIGURATION[:default_expires_in] = options[:default_expires_in] if options[:default_expires_in]
|
32
32
|
|
33
33
|
ActiveRecord::Base.extend(Kasket::ConfigurationMixin)
|
34
|
-
|
35
|
-
|
36
|
-
ActiveRecord::Relation.include Kasket::RelationMixin
|
37
|
-
Arel::SelectManager.include Kasket::SelectManagerMixin
|
38
|
-
end
|
34
|
+
ActiveRecord::Relation.include(Kasket::RelationMixin)
|
35
|
+
Arel::SelectManager.include(Kasket::SelectManagerMixin)
|
39
36
|
end
|
40
37
|
|
41
38
|
def self.cache_store=(options)
|
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.
|
4
|
+
version: 4.12.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:
|
12
|
+
date: 2023-03-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -17,20 +17,20 @@ dependencies:
|
|
17
17
|
requirements:
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '5.1'
|
21
21
|
- - "<"
|
22
22
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
23
|
+
version: '7'
|
24
24
|
type: :runtime
|
25
25
|
prerelease: false
|
26
26
|
version_requirements: !ruby/object:Gem::Requirement
|
27
27
|
requirements:
|
28
28
|
- - ">="
|
29
29
|
- !ruby/object:Gem::Version
|
30
|
-
version: '
|
30
|
+
version: '5.1'
|
31
31
|
- - "<"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '7'
|
34
34
|
description: puts a cap on your queries
|
35
35
|
email:
|
36
36
|
- mick@zendesk.com
|
@@ -61,7 +61,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
61
61
|
requirements:
|
62
62
|
- - ">="
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: 2.
|
64
|
+
version: 2.6.0
|
65
65
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - ">="
|