Module: SafeMemoize::Extension

Defined in:
lib/safe_memoize/extension.rb

Overview

Mixin for defining SafeMemoize extensions.

Extend this module in any Ruby module or class that you want to register as a SafeMemoize extension. It provides a DSL for declaring custom +memoize+ options and global cache lifecycle event handlers.

Examples:

Defining an extension

module MyExtension
  extend SafeMemoize::Extension

  handles_option :active_record_bust do |value, method_name, _options|
    { cache_bust: -> { send(:updated_at) } }
  end

  on_cache_event :miss do |klass, method_name, _cache_key, _record|
    Rails.logger.debug "cache miss: #{klass}##{method_name}"
  end
end

SafeMemoize.register_extension(:active_record_bust, MyExtension)

Instance Method Summary collapse

Instance Method Details

#dispatch_cache_event(event_type, klass, method_name, cache_key, record) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



80
81
82
83
84
85
86
# File 'lib/safe_memoize/extension.rb', line 80

def dispatch_cache_event(event_type, klass, method_name, cache_key, record)
  return unless @__event_handlers__

  (@__event_handlers__[event_type] || []).each do |handler|
    handler.call(klass, method_name, cache_key, record)
  end
end

#handled_optionsObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



68
69
70
# File 'lib/safe_memoize/extension.rb', line 68

def handled_options
  @__handled_options__&.keys || []
end

#handles_option(option_name) {|value, method_name, all_options| ... } ⇒ void

This method returns an undefined value.

Declares a custom +memoize+ option handled by this extension.

The block is called at +memoize+ definition time whenever +option_name+ appears in the +memoize+ keyword arguments. It receives the option value, the method name being memoized, and the full hash of other extension options passed to that +memoize+ call. It must return a +Hash+ of standard ClassMethods#memoize options to inject (e.g. +{ cache_bust: ... }+), or +nil+/empty hash for no injection.

Parameters:

  • option_name (Symbol)

Yield Parameters:

  • value (Object)

    the option value supplied by the caller

  • method_name (Symbol)

    the method being memoized

  • all_options (Hash)

    other extension options in the same +memoize+ call

Yield Returns:

  • (Hash, nil)

    standard memoize options to inject



40
41
42
43
# File 'lib/safe_memoize/extension.rb', line 40

def handles_option(option_name, &processor)
  @__handled_options__ ||= {}
  @__handled_options__[option_name.to_sym] = processor
end

#on_cache_event(*event_types) {|klass, method_name, cache_key, record| ... } ⇒ void

This method returns an undefined value.

Registers a global cache lifecycle event handler.

The block fires after every matching cache event across all memoized methods on all classes. Multiple event types can be listed in a single call. Valid types are +:on_hit+, +:on_miss+, +:on_store+, +:on_expire+, and +:on_evict+.

Handlers execute on the main Ractor only; they are silently skipped from worker Ractors.

Parameters:

  • event_types (Array<Symbol>)

    one or more of +:on_hit+, +:on_miss+, +:on_store+, +:on_expire+, +:on_evict+

Yield Parameters:

  • klass (Class)

    the class whose instance triggered the event

  • method_name (Symbol)

    bare method name (namespace stripped)

  • cache_key (Array)

    the full cache key

  • record (Hash, nil)

    the cache record (+value+, +expires_at+, +cached_at+)



62
63
64
65
# File 'lib/safe_memoize/extension.rb', line 62

def on_cache_event(*event_types, &handler)
  @__event_handlers__ ||= {}
  event_types.each { |type| (@__event_handlers__[type.to_sym] ||= []) << handler }
end

#process_memoize_option(option_name, value, method_name, all_options) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



73
74
75
76
77
# File 'lib/safe_memoize/extension.rb', line 73

def process_memoize_option(option_name, value, method_name, all_options)
  processor = @__handled_options__&.[](option_name.to_sym)
  result = processor&.call(value, method_name, all_options)
  result.is_a?(Hash) ? result : {}
end