ttl_memoizeable 0.3.0 → 0.4.1
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/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/README.md +26 -2
- data/lib/ttl_memoizeable/version.rb +1 -1
- data/lib/ttl_memoizeable.rb +26 -4
- metadata +3 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c5d04e1b3ea5834552d353149bdecbe3e34e665ff81309cf2ec235c0a1948b0d
|
|
4
|
+
data.tar.gz: 10f4a41c7671cb6ed3b8a82006b9f21610d9e6a74b22a4808e2ae99e60ed9704
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 773703b9c7190e19474cef1b049a26ec0458c9a9ab4393e72364b96ec2fb913d3e3efdb19885f02eed2ca1ece6bebb42614b6edf297551d4b36ce48247c9ff6b
|
|
7
|
+
data.tar.gz: 709f01839f542b3c7c82ad828d0ffd5533286840bc0769c2e113be739ab9843a5b737a5ed346b3944722faaea4ebf494dea14401bb1a3cae4f0a78c765555083
|
data/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
|
+
## [0.4.1] - 2026-09-25
|
|
3
|
+
- Calculate TTL using monotonic time, which is much more performant (#16) @kbennoune
|
|
4
|
+
## [0.4.0] - 2024-09-18
|
|
5
|
+
- Add support for globally disabling TTLMemoizeable (#15) @danielwestendorf
|
|
6
|
+
- Add support for globally resetting all ttls (#13) @danielwestendorf
|
|
2
7
|
## [0.3.0] - 2024-01-04
|
|
3
8
|
- Bug fixes
|
|
4
9
|
## [0.2.0] - 2023-11-27
|
data/Gemfile
CHANGED
data/README.md
CHANGED
|
@@ -151,7 +151,7 @@ application_config.config # => {...} Redis/JSON.parse will be called
|
|
|
151
151
|
|
|
152
152
|
## Testing a TTLMemoized Method
|
|
153
153
|
|
|
154
|
-
You likely don't want to test the implementation of this library, but the logic of your memoized method. In that case you probably want "fresh" data on every invocation of the method. There are
|
|
154
|
+
You likely don't want to test the implementation of this library, but the logic of your memoized method. In that case you probably want "fresh" data on every invocation of the method. There are a few approaches, depending on your preference of flavor.
|
|
155
155
|
|
|
156
156
|
1. Use the reset method provided for you. It follows the pattern of `reset_memoized_value_for_#{method_name}`. Note that this will only reset the value for the current thread, and shouldn't be used to try and create consistent data state across processes.
|
|
157
157
|
```ruby
|
|
@@ -162,7 +162,31 @@ def test_config
|
|
|
162
162
|
end
|
|
163
163
|
```
|
|
164
164
|
|
|
165
|
-
2.
|
|
165
|
+
2. Disable ttl memoization globally in your tests. This will prevent a memoized value from ever being returned.
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
TTLMemoizeable.disable!
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
3. Reset ttl memoization values before/after your test runs.
|
|
172
|
+
|
|
173
|
+
```ruby
|
|
174
|
+
# RSpec
|
|
175
|
+
RSpec.configure do |config|
|
|
176
|
+
config.around { TTLMemoizeable.reset!; _1.run; TTLMemoizeable.reset! }
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# minitest
|
|
180
|
+
def setup
|
|
181
|
+
TTLMemoizeable.reset!
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
def teardown
|
|
185
|
+
TTLMemoizeable.reset!
|
|
186
|
+
end
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
4. Conditionally TTL memoize the method based on test environment or some other condition.
|
|
166
190
|
```ruby
|
|
167
191
|
def config
|
|
168
192
|
JSON.parse($redis.get("some_big_json_string"))
|
data/lib/ttl_memoizeable.rb
CHANGED
|
@@ -8,15 +8,29 @@ require_relative "ttl_memoizeable/version"
|
|
|
8
8
|
module TTLMemoizeable
|
|
9
9
|
TTLMemoizationError = Class.new(StandardError)
|
|
10
10
|
SetupMutex = Mutex.new
|
|
11
|
+
EXPIRED_MONOTONIC_TIME = -365.0 * 24 * 60 * 60 # one year before the monotonic clock origin
|
|
12
|
+
|
|
13
|
+
@ttl_index = 0
|
|
14
|
+
@disabled = false
|
|
15
|
+
|
|
16
|
+
def self.disable!
|
|
17
|
+
@disabled = true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.reset!
|
|
21
|
+
@ttl_index += 1
|
|
22
|
+
end
|
|
11
23
|
|
|
12
24
|
def ttl_memoized_method(method_name, ttl: 1000)
|
|
13
25
|
raise TTLMemoizationError, "Method not defined: #{method_name}" unless method_defined?(method_name) || private_method_defined?(method_name)
|
|
14
26
|
|
|
15
27
|
ivar_name = method_name.to_s.gsub(/\??/, "") # remove trailing question marks
|
|
16
28
|
time_based_ttl = ttl.is_a?(ActiveSupport::Duration)
|
|
17
|
-
|
|
29
|
+
ttl_seconds = ttl.to_f if time_based_ttl
|
|
30
|
+
expired_ttl = time_based_ttl ? EXPIRED_MONOTONIC_TIME : 1
|
|
18
31
|
|
|
19
32
|
ttl_variable_name = :"@_ttl_for_#{ivar_name}"
|
|
33
|
+
ttl_index_variable_name = :"@_ttl_index_for_#{ivar_name}"
|
|
20
34
|
mutex_variable_name = :"@_mutex_for_#{ivar_name}"
|
|
21
35
|
value_variable_name = :"@_value_for_#{ivar_name}"
|
|
22
36
|
|
|
@@ -60,15 +74,20 @@ module TTLMemoizeable
|
|
|
60
74
|
end
|
|
61
75
|
|
|
62
76
|
define_method ttl_exceeded_method_name do
|
|
77
|
+
return true if TTLMemoizeable.instance_variable_get(:@disabled)
|
|
78
|
+
return true if TTLMemoizeable.instance_variable_get(:@ttl_index) != instance_variable_get(ttl_index_variable_name)
|
|
63
79
|
return true unless instance_variable_defined?(value_variable_name)
|
|
64
80
|
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
if time_based_ttl
|
|
82
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) - instance_variable_get(ttl_variable_name) >= ttl_seconds
|
|
83
|
+
else
|
|
84
|
+
instance_variable_get(ttl_variable_name) <= 0
|
|
85
|
+
end
|
|
67
86
|
end
|
|
68
87
|
|
|
69
88
|
define_method extend_ttl_method_name do
|
|
70
89
|
if time_based_ttl
|
|
71
|
-
instance_variable_set(ttl_variable_name,
|
|
90
|
+
instance_variable_set(ttl_variable_name, Process.clock_gettime(Process::CLOCK_MONOTONIC))
|
|
72
91
|
else
|
|
73
92
|
instance_variable_set(ttl_variable_name, ttl)
|
|
74
93
|
end
|
|
@@ -85,6 +104,9 @@ module TTLMemoizeable
|
|
|
85
104
|
if send(ttl_exceeded_method_name)
|
|
86
105
|
send(extend_ttl_method_name)
|
|
87
106
|
|
|
107
|
+
# Synchronize the ttl index to match the module's value
|
|
108
|
+
instance_variable_set(ttl_index_variable_name, TTLMemoizeable.instance_variable_get(:@ttl_index))
|
|
109
|
+
|
|
88
110
|
# Refresh value from the original method
|
|
89
111
|
instance_variable_set(value_variable_name, super())
|
|
90
112
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ttl_memoizeable
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel Westendorf
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activesupport
|
|
@@ -61,7 +60,6 @@ licenses:
|
|
|
61
60
|
metadata:
|
|
62
61
|
homepage_uri: https://github.com/huntresslabs/ttl_memoizeable
|
|
63
62
|
source_code_uri: https://github.com/huntresslabs/ttl_memoizeable
|
|
64
|
-
post_install_message:
|
|
65
63
|
rdoc_options: []
|
|
66
64
|
require_paths:
|
|
67
65
|
- lib
|
|
@@ -76,8 +74,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
76
74
|
- !ruby/object:Gem::Version
|
|
77
75
|
version: '0'
|
|
78
76
|
requirements: []
|
|
79
|
-
rubygems_version:
|
|
80
|
-
signing_key:
|
|
77
|
+
rubygems_version: 4.0.16
|
|
81
78
|
specification_version: 4
|
|
82
79
|
summary: Cross-thread memoization in ruby with eventual consistency.
|
|
83
80
|
test_files: []
|