Module: SafeMemoize::PublicMethods

Included in:
InstanceMethods
Defined in:
lib/safe_memoize/public_methods.rb

Instance Method Summary collapse

Instance Method Details

#clear_memo_hooks(hook_type = nil) ⇒ Object



84
85
86
87
88
# File 'lib/safe_memoize/public_methods.rb', line 84

def clear_memo_hooks(hook_type = nil)
  with_memo_lock do
    _clear_memo_hooks(hook_type)
  end
end

#dump_memo(method_name = nil) ⇒ Object



114
115
116
117
118
119
120
121
122
123
# File 'lib/safe_memoize/public_methods.rb', line 114

def dump_memo(method_name = nil)
  method_name = method_name&.to_sym

  with_memo_lock do
    cache = memo_cache_or_nil || {}
    entries = method_name ? cache.select { |key, _| key[0] == method_name } : cache.dup
    entries.select! { |_, record| memo_record_live?(record) }
    entries.transform_values { |record| memo_record_value(record) }
  end
end

#load_memo(snapshot) ⇒ Object

Raises:

  • (ArgumentError)


125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/safe_memoize/public_methods.rb', line 125

def load_memo(snapshot)
  raise ArgumentError, "snapshot must be a Hash" unless snapshot.is_a?(Hash)

  with_memo_lock do
    @__safe_memo_cache__ ||= {}
    snapshot.each do |cache_key, value|
      record = memo_record(value, expires_at: nil)
      @__safe_memo_cache__[cache_key] = record
      call_memo_hooks(:on_store, cache_key, record)
    end
  end

  nil
end

#memo_age(method_name, *args, **kwargs) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/safe_memoize/public_methods.rb', line 171

def memo_age(method_name, *args, **kwargs)
  cache_key = safe_memo_cache_key(method_name, args, kwargs)

  with_memo_lock do
    record = memo_cache_record(cache_key)
    return nil unless record

    cached_at = record[:cached_at]
    return nil unless cached_at

    (Process.clock_gettime(Process::CLOCK_MONOTONIC) - cached_at).round(6)
  end
end

#memo_count(*method_name) ⇒ Object



30
31
32
33
34
35
36
# File 'lib/safe_memoize/public_methods.rb', line 30

def memo_count(*method_name)
  scoped_method = safe_memo_scoped_method(method_name)

  with_memo_lock do
    safe_memo_count_for(scoped_method)
  end
end

#memo_keys(*method_name) ⇒ Object



38
39
40
41
42
43
44
# File 'lib/safe_memoize/public_methods.rb', line 38

def memo_keys(*method_name)
  scoped_method = safe_memo_scoped_method(method_name)

  with_memo_lock do
    safe_memo_keys_for(scoped_method)
  end
end

#memo_preload(method_name, *arg_sets) ⇒ Object



107
108
109
110
111
112
# File 'lib/safe_memoize/public_methods.rb', line 107

def memo_preload(method_name, *arg_sets)
  method_name = method_name.to_sym
  arg_sets.map do |args|
    send(method_name, *Array(args))
  end
end

#memo_refresh(method_name, *args, **kwargs) ⇒ Object



165
166
167
168
169
# File 'lib/safe_memoize/public_methods.rb', line 165

def memo_refresh(method_name, *args, **kwargs)
  method_name = method_name.to_sym
  reset_memo(method_name, *args, **kwargs)
  send(method_name, *args, **kwargs)
end

#memo_stale?(method_name, *args, **kwargs) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/safe_memoize/public_methods.rb', line 185

def memo_stale?(method_name, *args, **kwargs)
  cache_key = safe_memo_cache_key(method_name, args, kwargs)

  with_memo_lock do
    cache = memo_cache_or_nil
    return false unless cache

    record = cache[cache_key]
    return false unless record

    !memo_record_live?(record)
  end
end

#memo_touch(method_name, *args, ttl: nil, **kwargs) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/safe_memoize/public_methods.rb', line 140

def memo_touch(method_name, *args, ttl: nil, **kwargs)
  method_name = method_name.to_sym
  cache_key = safe_memo_cache_key(method_name, args, kwargs)

  with_memo_lock do
    cache = memo_cache_or_nil
    return false unless cache

    record = cache[cache_key]
    return false unless record && memo_record_live?(record)

    now = Process.clock_gettime(Process::CLOCK_MONOTONIC)

    effective_ttl = if ttl
      ttl
    elsif record[:expires_at] && record[:cached_at]
      record[:expires_at] - record[:cached_at]
    end

    record[:expires_at] = effective_ttl ? now + effective_ttl : nil
    record[:cached_at] = now
    true
  end
end

#memo_ttl_remaining(method_name, *args, **kwargs) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/safe_memoize/public_methods.rb', line 15

def memo_ttl_remaining(method_name, *args, **kwargs)
  cache_key = safe_memo_cache_key(method_name, args, kwargs)

  with_memo_lock do
    record = memo_cache_record(cache_key)
    return 0 unless record

    expires_at = record[:expires_at]
    return nil unless expires_at

    remaining = expires_at - Process.clock_gettime(Process::CLOCK_MONOTONIC)
    (remaining > 0) ? remaining.round(6) : 0
  end
end

#memo_values(*method_name) ⇒ Object



46
47
48
49
50
51
52
# File 'lib/safe_memoize/public_methods.rb', line 46

def memo_values(*method_name)
  scoped_method = safe_memo_scoped_method(method_name)

  with_memo_lock do
    safe_memo_values_for(scoped_method)
  end
end

#memoized?(method_name, *args, **kwargs, &block) ⇒ Boolean

Returns:

  • (Boolean)


5
6
7
8
9
10
11
12
13
# File 'lib/safe_memoize/public_methods.rb', line 5

def memoized?(method_name, *args, **kwargs, &block)
  return false if block

  cache_key = safe_memo_cache_key(method_name, args, kwargs)

  with_memo_lock do
    memo_cache_hit?(cache_key)
  end
end

#on_memo_evict(&block) ⇒ Object

Raises:

  • (ArgumentError)


60
61
62
63
64
# File 'lib/safe_memoize/public_methods.rb', line 60

def on_memo_evict(&block)
  raise ArgumentError, "block required" unless block

  register_memo_hook(:on_evict, &block)
end

#on_memo_expire(&block) ⇒ Object

Raises:

  • (ArgumentError)


54
55
56
57
58
# File 'lib/safe_memoize/public_methods.rb', line 54

def on_memo_expire(&block)
  raise ArgumentError, "block required" unless block

  register_memo_hook(:on_expire, &block)
end

#on_memo_hit(&block) ⇒ Object

Raises:

  • (ArgumentError)


66
67
68
69
70
# File 'lib/safe_memoize/public_methods.rb', line 66

def on_memo_hit(&block)
  raise ArgumentError, "block required" unless block

  register_memo_hook(:on_hit, &block)
end

#on_memo_miss(&block) ⇒ Object

Raises:

  • (ArgumentError)


72
73
74
75
76
# File 'lib/safe_memoize/public_methods.rb', line 72

def on_memo_miss(&block)
  raise ArgumentError, "block required" unless block

  register_memo_hook(:on_miss, &block)
end

#on_memo_store(&block) ⇒ Object

Raises:

  • (ArgumentError)


78
79
80
81
82
# File 'lib/safe_memoize/public_methods.rb', line 78

def on_memo_store(&block)
  raise ArgumentError, "block required" unless block

  register_memo_hook(:on_store, &block)
end

#reset_all_memosObject



218
219
220
221
222
223
224
225
226
227
228
# File 'lib/safe_memoize/public_methods.rb', line 218

def reset_all_memos
  with_memo_lock do
    if defined?(@__safe_memo_cache__) && @__safe_memo_cache__
      @__safe_memo_cache__.each do |key, record|
        call_memo_hooks(:on_evict, key, record)
      end
    end
    @__safe_memo_cache__ = {}
    lru_clear_all
  end
end

#reset_memo(method_name, *args, **kwargs) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/safe_memoize/public_methods.rb', line 199

def reset_memo(method_name, *args, **kwargs)
  method_name = method_name.to_sym

  matcher = memo_matcher_for(method_name, args, kwargs)

  with_memo_lock do
    with_memo_cache do |cache|
      cache.delete_if do |key, record|
        if matcher.call(key)
          call_memo_hooks(:on_evict, key, record)
          true
        else
          false
        end
      end
    end
  end
end

#warm_memo(method_name, *args, ttl: nil, **kwargs, &block) ⇒ Object

Raises:

  • (ArgumentError)


90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/safe_memoize/public_methods.rb', line 90

def warm_memo(method_name, *args, ttl: nil, **kwargs, &block)
  raise ArgumentError, "block required" unless block

  method_name = method_name.to_sym
  cache_key = compute_cache_key(method_name, args, kwargs)
  value = block.call

  with_memo_lock do
    @__safe_memo_cache__ ||= {}
    record = memo_record(value, expires_at: memo_expires_at(ttl))
    @__safe_memo_cache__[cache_key] = record
    call_memo_hooks(:on_store, cache_key, record)
  end

  value
end