Class: LaunchDarkly::Integrations::Util::CachingStoreWrapper

Inherits:
Object
  • Object
show all
Includes:
LaunchDarkly::Interfaces::FeatureStore
Defined in:
lib/ldclient-rb/integrations/util/store_wrapper.rb

Overview

CachingStoreWrapper is a partial implementation of the LaunchDarkly::Interfaces::FeatureStore pattern that delegates part of its behavior to another object, while providing optional caching behavior and other logic that would otherwise be repeated in every feature store implementation. This makes it easier to create new database integrations by implementing only the database-specific logic.

The mixin FeatureStoreCore describes the methods that need to be supported by the inner implementation object.

Since:

  • 5.5.0

Instance Method Summary collapse

Constructor Details

#initialize(core, opts) ⇒ CachingStoreWrapper

Creates a new store wrapper instance.

Parameters:

  • core (Object)

    an object that implements the FeatureStoreCore methods

  • opts (Hash)

    a hash that may include cache-related options; all others will be ignored

Options Hash (opts):

  • :expiration (Float) — default: 15

    cache TTL; zero means no caching

  • :capacity (Integer) — default: 1000

    maximum number of items in the cache

Since:

  • 5.5.0



29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 29

def initialize(core, opts)
  @core = core

  expiration_seconds = opts[:expiration] || 15
  if expiration_seconds > 0
    capacity = opts[:capacity] || 1000
    @cache = ExpiringCache.new(capacity, expiration_seconds)
  else
    @cache = nil
  end

  @inited = Concurrent::AtomicBoolean.new(false)
end

Instance Method Details

#all(kind) ⇒ Object

Since:

  • 5.5.0



74
75
76
77
78
79
80
81
82
83
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 74

def all(kind)
  if !@cache.nil?
    items = @cache[all_cache_key(kind)]
    return items if !items.nil?
  end

  items = items_if_not_deleted(@core.get_all_internal(kind))
  @cache[all_cache_key(kind)] = items if !@cache.nil?
  items
end

#delete(kind, key, version) ⇒ Object

Since:

  • 5.5.0



94
95
96
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 94

def delete(kind, key, version)
  upsert(kind, { key: key, version: version, deleted: true })
end

#get(kind, key) ⇒ Object

Since:

  • 5.5.0



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 58

def get(kind, key)
  if !@cache.nil?
    cache_key = item_cache_key(kind, key)
    cached = @cache[cache_key] # note, item entries in the cache are wrapped in an array so we can cache nil values
    return item_if_not_deleted(cached[0]) if !cached.nil?
  end

  item = @core.get_internal(kind, key)

  if !@cache.nil?
    @cache[cache_key] = [item]
  end

  item_if_not_deleted(item)
end

#init(all_data) ⇒ Object

Since:

  • 5.5.0



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 43

def init(all_data)
  @core.init_internal(all_data)
  @inited.make_true

  if !@cache.nil?
    @cache.clear
    all_data.each do |kind, items|
      @cache[kind] = items_if_not_deleted(items)
      items.each do |key, item|
        @cache[item_cache_key(kind, key)] = [item]
      end
    end
  end
end

#initialized?Boolean

Returns:

  • (Boolean)

Since:

  • 5.5.0



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 98

def initialized?
  return true if @inited.value

  if @cache.nil?
    result = @core.initialized_internal?
  else
    result = @cache[inited_cache_key]
    if result.nil?
      result = @core.initialized_internal?
      @cache[inited_cache_key] = result
    end
  end

  @inited.make_true if result
  result
end

#stopObject

Since:

  • 5.5.0



115
116
117
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 115

def stop
  @core.stop
end

#upsert(kind, item) ⇒ Object

Since:

  • 5.5.0



85
86
87
88
89
90
91
92
# File 'lib/ldclient-rb/integrations/util/store_wrapper.rb', line 85

def upsert(kind, item)
  new_state = @core.upsert_internal(kind, item)

  if !@cache.nil?
    @cache[item_cache_key(kind, item[:key])] = [new_state]
    @cache.delete(all_cache_key(kind))
  end
end