Class: LaunchDarkly::Impl::Integrations::DynamoDB::DynamoDBFeatureStoreCore

Inherits:
DynamoDBStoreImplBase show all
Defined in:
lib/ldclient-rb/impl/integrations/dynamodb_impl.rb

Overview

Internal implementation of the DynamoDB feature store, intended to be used with CachingStoreWrapper.

Since:

  • 5.5.0

Constant Summary collapse

VERSION_ATTRIBUTE =

Since:

  • 5.5.0

"version"
ITEM_JSON_ATTRIBUTE =

Since:

  • 5.5.0

"item"

Instance Method Summary collapse

Constructor Details

#initialize(table_name, opts) ⇒ DynamoDBFeatureStoreCore

Returns a new instance of DynamoDBFeatureStoreCore.

Since:

  • 5.5.0



57
58
59
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 57

def initialize(table_name, opts)
  super(table_name, opts)
end

Instance Method Details

#available?Boolean

Returns:

  • (Boolean)

Since:

  • 5.5.0



65
66
67
68
69
70
71
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 65

def available?
  resp = get_item_by_keys(inited_key, inited_key)
  !resp.item.nil? && resp.item.length > 0
  true
rescue
  false
end

#descriptionObject

Since:

  • 5.5.0



61
62
63
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 61

def description
  "DynamoDBFeatureStore"
end

#get_all_internal(kind) ⇒ Object

Since:

  • 5.5.0



109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 109

def get_all_internal(kind)
  items_out = {}
  req = make_query_for_kind(kind)
  while true
    resp = @client.query(req)
    resp.items.each do |item|
      item_out = unmarshal_item(kind, item)
      items_out[item_out[:key].to_sym] = item_out
    end
    break if resp.last_evaluated_key.nil? || resp.last_evaluated_key.length == 0
    req.exclusive_start_key = resp.last_evaluated_key
  end
  items_out
end

#get_internal(kind, key) ⇒ Object

Since:

  • 5.5.0



104
105
106
107
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 104

def get_internal(kind, key)
  resp = get_item_by_keys(namespace_for_kind(kind), key)
  unmarshal_item(kind, resp.item)
end

#init_internal(all_data) ⇒ Object

Since:

  • 5.5.0



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 73

def init_internal(all_data)
  # Start by reading the existing keys; we will later delete any of these that weren't in all_data.
  unused_old_keys = read_existing_keys(all_data.keys)

  requests = []
  num_items = 0

  # Insert or update every provided item
  all_data.each do |kind, items|
    items.values.each do |item|
      requests.push({ put_request: { item: marshal_item(kind, item) } })
      unused_old_keys.delete([ namespace_for_kind(kind), item[:key] ])
      num_items = num_items + 1
    end
  end

  # Now delete any previously existing items whose keys were not in the current data
  unused_old_keys.each do |tuple|
    del_item = make_keys_hash(tuple[0], tuple[1])
    requests.push({ delete_request: { key: del_item } })
  end

  # Now set the special key that we check in initialized_internal?
  inited_item = make_keys_hash(inited_key, inited_key)
  requests.push({ put_request: { item: inited_item } })

  DynamoDBUtil.batch_write_requests(@client, @table_name, requests)

  @logger.info { "Initialized table #{@table_name} with #{num_items} items" }
end

#initialized_internal?Boolean

Returns:

  • (Boolean)

Since:

  • 5.5.0



148
149
150
151
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 148

def initialized_internal?
  resp = get_item_by_keys(inited_key, inited_key)
  !resp.item.nil? && resp.item.length > 0
end

#upsert_internal(kind, new_item) ⇒ Object

Since:

  • 5.5.0



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
# File 'lib/ldclient-rb/impl/integrations/dynamodb_impl.rb', line 124

def upsert_internal(kind, new_item)
  encoded_item = marshal_item(kind, new_item)
  begin
    @client.put_item({
      table_name: @table_name,
      item: encoded_item,
      condition_expression: "attribute_not_exists(#namespace) or attribute_not_exists(#key) or :version > #version",
      expression_attribute_names: {
        "#namespace" => PARTITION_KEY,
        "#key" => SORT_KEY,
        "#version" => VERSION_ATTRIBUTE,
      },
      expression_attribute_values: {
        ":version" => new_item[:version],
      },
    })
    new_item
  rescue Aws::DynamoDB::Errors::ConditionalCheckFailedException
    # The item was not updated because there's a newer item in the database.
    # We must now read the item that's in the database and return it, so CachingStoreWrapper can cache it.
    get_internal(kind, new_item[:key])
  end
end