kasket 4.13.0 → 4.14.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 +13 -0
- data/lib/kasket/events.rb +34 -0
- data/lib/kasket/read_mixin.rb +10 -0
- data/lib/kasket/version.rb +1 -1
- data/lib/kasket.rb +15 -1
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6e7fba4b86593d0f6df819b8e4af5417db71843ca84f6aa713688fad70af03d
|
4
|
+
data.tar.gz: d0b55338667baf18f1f85b74eb6063e1c2c216fb66bcc6f66c8f0c72a8233b58
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 258485dd05909a3741841bac6ef9c1fbf41ac37c8978f9efa2284cf0caa3a05dbc38ba76c7f74b8ee033ff6106ddbbcd9a0b86943323e08e4e2dd8d95ee86a99
|
7
|
+
data.tar.gz: bf59e003102eef756e49977f99441e4f0930c0032bce7dc183f47e27b2e0887f5d682bdb1b34cd5e3892136e9ebf21d18dbe9ad5c685d3daaf8271b2d5c4c2a1
|
data/README.md
CHANGED
@@ -48,6 +48,19 @@ semantics instead. In this mode, the model will be updated in the cache as well
|
|
48
48
|
Kasket.setup(write_through: true)
|
49
49
|
```
|
50
50
|
|
51
|
+
#### Events Callback
|
52
|
+
|
53
|
+
You can configure a callable object to listen to events. This can be useful to emit metrics and observe Kasket's behaviour.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
Kasket.setup(events_callback: -> (event, ar_klass) do
|
57
|
+
MyMetrics.increase_some_counter("kasket.#{event}", tags: ["table:#{ar_klass.table_name}"])
|
58
|
+
end)
|
59
|
+
```
|
60
|
+
|
61
|
+
The following events are emitted:
|
62
|
+
* `"cache_hit"`, when Kasket has found some record's data in the cache, which can be returned.
|
63
|
+
|
51
64
|
## Configuring caching of your models
|
52
65
|
|
53
66
|
You can configure Kasket for any ActiveRecord model, and subclasses will automatically inherit the caching
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kasket
|
4
|
+
# Interface to the internal instrumentation event.
|
5
|
+
module Events
|
6
|
+
class << self
|
7
|
+
# Invokes the configured events callback, if provided.
|
8
|
+
#
|
9
|
+
# The callback behaves like a listener, and receives the same arguments
|
10
|
+
# that are passed to this `report` method.
|
11
|
+
#
|
12
|
+
# @param [String] event the type of event being instrumented.
|
13
|
+
# @param [class] ar_klass the ActiveRecord::Base subclass that the event
|
14
|
+
# refers to.
|
15
|
+
#
|
16
|
+
# @return [nil]
|
17
|
+
#
|
18
|
+
def report(event, ar_klass)
|
19
|
+
return unless fn
|
20
|
+
|
21
|
+
fn.call(event, ar_klass)
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def fn
|
28
|
+
return @fn if defined?(@fn)
|
29
|
+
|
30
|
+
@fn = Kasket::CONFIGURATION[:events_callback]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/kasket/read_mixin.rb
CHANGED
@@ -36,8 +36,15 @@ module Kasket
|
|
36
36
|
result_set = if value.is_a?(TrueClass)
|
37
37
|
find_by_sql_without_kasket(sql, binds, *restargs, **kwargs, &blk)
|
38
38
|
elsif value.is_a?(Array)
|
39
|
+
# The data from the Kasket cache is a list of keys to other Kasket entries.
|
40
|
+
# This usually happens when we're trying to load a collection association,
|
41
|
+
# e.g. a list of comments using their post_id in the query.
|
42
|
+
# Do not report a cache hit yet, and defer it until we've verified that at
|
43
|
+
# least one of the retrieved keys is actually in the cache.
|
39
44
|
filter_pending_records(find_by_sql_with_kasket_on_id_array(value))
|
40
45
|
else
|
46
|
+
# Direct cache hit for the key.
|
47
|
+
Events.report("cache_hit", self)
|
41
48
|
filter_pending_records(Array.wrap(value).collect { |record| instantiate(record.dup, &blk) })
|
42
49
|
end
|
43
50
|
|
@@ -60,6 +67,9 @@ module Kasket
|
|
60
67
|
key_attributes_map = Kasket.cache.read_multi(*keys)
|
61
68
|
|
62
69
|
found_keys, missing_keys = keys.partition {|k| key_attributes_map[k] }
|
70
|
+
# Only report a cache hit if at least some keys were found in the cache.
|
71
|
+
Events.report("cache_hit", self) if found_keys.any?
|
72
|
+
|
63
73
|
found_keys.each {|k| key_attributes_map[k] = instantiate(key_attributes_map[k].dup, &blk) }
|
64
74
|
key_attributes_map.merge!(missing_records_from_db(missing_keys))
|
65
75
|
|
data/lib/kasket/version.rb
CHANGED
data/lib/kasket.rb
CHANGED
@@ -14,21 +14,35 @@ module Kasket
|
|
14
14
|
autoload :Visitor, 'kasket/visitor'
|
15
15
|
autoload :SelectManagerMixin, 'kasket/select_manager_mixin'
|
16
16
|
autoload :RelationMixin, 'kasket/relation_mixin'
|
17
|
+
autoload :Events, 'kasket/events'
|
17
18
|
|
18
19
|
CONFIGURATION = { # rubocop:disable Style/MutableConstant
|
19
20
|
max_collection_size: 100,
|
20
21
|
write_through: false,
|
21
|
-
default_expires_in: nil
|
22
|
+
default_expires_in: nil,
|
23
|
+
events_callback: nil,
|
22
24
|
}
|
23
25
|
|
24
26
|
module_function
|
25
27
|
|
28
|
+
# Configure Kasket.
|
29
|
+
#
|
30
|
+
# @param [Hash] options the configuration options for Kasket.
|
31
|
+
# @option options [Integer] :max_collection_size max size limit for a cacheable
|
32
|
+
# collection of records.
|
33
|
+
# @option options [Boolean] :write_through
|
34
|
+
# @option options [Integer, nil] :default_expires_in the cache TTL.
|
35
|
+
# @option options [#call] :events_callback a callable object used to instrument
|
36
|
+
# Kasket operations. It is invoked with two arguments: the name of the event,
|
37
|
+
# as a String, and the Klass of the ActiveRecord model the event is about.
|
38
|
+
#
|
26
39
|
def setup(options = {})
|
27
40
|
return if ActiveRecord::Base.respond_to?(:has_kasket)
|
28
41
|
|
29
42
|
CONFIGURATION[:max_collection_size] = options[:max_collection_size] if options[:max_collection_size]
|
30
43
|
CONFIGURATION[:write_through] = options[:write_through] if options[:write_through]
|
31
44
|
CONFIGURATION[:default_expires_in] = options[:default_expires_in] if options[:default_expires_in]
|
45
|
+
CONFIGURATION[:events_callback] = options[:events_callback] if options[:events_callback]
|
32
46
|
|
33
47
|
ActiveRecord::Base.extend(Kasket::ConfigurationMixin)
|
34
48
|
ActiveRecord::Relation.include(Kasket::RelationMixin)
|
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.14.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: 2024-01-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- lib/kasket.rb
|
43
43
|
- lib/kasket/configuration_mixin.rb
|
44
44
|
- lib/kasket/dirty_mixin.rb
|
45
|
+
- lib/kasket/events.rb
|
45
46
|
- lib/kasket/query_parser.rb
|
46
47
|
- lib/kasket/read_mixin.rb
|
47
48
|
- lib/kasket/relation_mixin.rb
|
@@ -68,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
68
69
|
- !ruby/object:Gem::Version
|
69
70
|
version: '0'
|
70
71
|
requirements: []
|
71
|
-
rubygems_version: 3.
|
72
|
+
rubygems_version: 3.5.3
|
72
73
|
signing_key:
|
73
74
|
specification_version: 4
|
74
75
|
summary: A write back caching layer on active record
|