Class: Flipper::Adapters::Memoizable

Inherits:
SimpleDelegator
  • Object
show all
Includes:
Flipper::Adapter
Defined in:
lib/flipper/adapters/memoizable.rb

Overview

Internal: Adapter that wraps another adapter with the ability to memoize adapter calls in memory. Used by flipper dsl and the memoizer middleware to make it possible to memoize adapter calls for the duration of a request.

Constant Summary collapse

FeaturesKey =
:flipper_features
GetAllKey =
:all_memoized

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Flipper::Adapter

#default_config, #import, included

Constructor Details

#initialize(adapter, cache = nil) ⇒ Memoizable

Public



29
30
31
32
33
34
35
# File 'lib/flipper/adapters/memoizable.rb', line 29

def initialize(adapter, cache = nil)
  super(adapter)
  @adapter = adapter
  @name = :memoizable
  @cache = cache || {}
  @memoize = false
end

Instance Attribute Details

#adapterObject (readonly)

Internal: The adapter this adapter is wrapping.



21
22
23
# File 'lib/flipper/adapters/memoizable.rb', line 21

def adapter
  @adapter
end

#cacheObject (readonly)

Internal



15
16
17
# File 'lib/flipper/adapters/memoizable.rb', line 15

def cache
  @cache
end

#nameObject (readonly)

Public: The name of the adapter.



18
19
20
# File 'lib/flipper/adapters/memoizable.rb', line 18

def name
  @name
end

Class Method Details

.key_for(key) ⇒ Object

Private



24
25
26
# File 'lib/flipper/adapters/memoizable.rb', line 24

def self.key_for(key)
  "feature/#{key}"
end

Instance Method Details

#add(feature) ⇒ Object

Public



47
48
49
50
51
# File 'lib/flipper/adapters/memoizable.rb', line 47

def add(feature)
  result = @adapter.add(feature)
  expire_features_set
  result
end

#clear(feature) ⇒ Object

Public



62
63
64
65
66
# File 'lib/flipper/adapters/memoizable.rb', line 62

def clear(feature)
  result = @adapter.clear(feature)
  expire_feature(feature)
  result
end

#disable(feature, gate, thing) ⇒ Object

Public



133
134
135
136
137
# File 'lib/flipper/adapters/memoizable.rb', line 133

def disable(feature, gate, thing)
  result = @adapter.disable(feature, gate, thing)
  expire_feature(feature)
  result
end

#enable(feature, gate, thing) ⇒ Object

Public



126
127
128
129
130
# File 'lib/flipper/adapters/memoizable.rb', line 126

def enable(feature, gate, thing)
  result = @adapter.enable(feature, gate, thing)
  expire_feature(feature)
  result
end

#featuresObject

Public



38
39
40
41
42
43
44
# File 'lib/flipper/adapters/memoizable.rb', line 38

def features
  if memoizing?
    cache.fetch(FeaturesKey) { cache[FeaturesKey] = @adapter.features }
  else
    @adapter.features
  end
end

#get(feature) ⇒ Object

Public



69
70
71
72
73
74
75
# File 'lib/flipper/adapters/memoizable.rb', line 69

def get(feature)
  if memoizing?
    cache.fetch(key_for(feature.key)) { cache[key_for(feature.key)] = @adapter.get(feature) }
  else
    @adapter.get(feature)
  end
end

#get_allObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/flipper/adapters/memoizable.rb', line 99

def get_all
  if memoizing?
    response = nil
    if cache[GetAllKey]
      response = {}
      cache[FeaturesKey].each do |key|
        response[key] = cache[key_for(key)]
      end
    else
      response = @adapter.get_all
      response.each do |key, value|
        cache[key_for(key)] = value
      end
      cache[FeaturesKey] = response.keys.to_set
      cache[GetAllKey] = true
    end

    # Ensures that looking up other features that do not exist doesn't
    # result in N+1 adapter calls.
    response.default_proc = ->(memo, key) { memo[key] = default_config }
    response
  else
    @adapter.get_all
  end
end

#get_multi(features) ⇒ Object

Public



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/flipper/adapters/memoizable.rb', line 78

def get_multi(features)
  if memoizing?
    uncached_features = features.reject { |feature| cache[key_for(feature.key)] }

    if uncached_features.any?
      response = @adapter.get_multi(uncached_features)
      response.each do |key, hash|
        cache[key_for(key)] = hash
      end
    end

    result = {}
    features.each do |feature|
      result[feature.key] = cache[key_for(feature.key)]
    end
    result
  else
    @adapter.get_multi(features)
  end
end

#memoize=(value) ⇒ Object

Internal: Turns local caching on/off.

value - The Boolean that decides if local caching is on.



142
143
144
145
# File 'lib/flipper/adapters/memoizable.rb', line 142

def memoize=(value)
  cache.clear
  @memoize = value
end

#memoizing?Boolean

Internal: Returns true for using local cache, false for not.

Returns:

  • (Boolean)


148
149
150
# File 'lib/flipper/adapters/memoizable.rb', line 148

def memoizing?
  !!@memoize
end

#remove(feature) ⇒ Object

Public



54
55
56
57
58
59
# File 'lib/flipper/adapters/memoizable.rb', line 54

def remove(feature)
  result = @adapter.remove(feature)
  expire_features_set
  expire_feature(feature)
  result
end