Module: Aws::Record::Transactions

Extended by:
ClientConfiguration
Defined in:
lib/aws-record/record/transactions.rb

Class Method Summary collapse

Methods included from ClientConfiguration

configure_client, dynamodb_client

Class Method Details

.transact_find(opts) ⇒ OpenStruct

Provides a way to run a transactional find across multiple DynamoDB items, including transactions which get items across multiple actual or virtual tables.

Examples:

Usage Example

class TableOne
  include Aws::Record
  string_attr :uuid, hash_key: true
end

class TableTwo
  include Aws::Record
  string_attr :hk, hash_key: true
  string_attr :rk, range_key: true
end

results = Aws::Record::Transactions.transact_find(
  transact_items: [
    TableOne.tfind_opts(key: { uuid: "uuid1234" }),
    TableTwo.tfind_opts(key: { hk: "hk1", rk: "rk1"}),
    TableTwo.tfind_opts(key: { hk: "hk2", rk: "rk2"})
  ]
) # => results.responses contains nil or marshalled items
results.responses.map { |r| r.class } # [TableOne, TableTwo, TableTwo]

Parameters:

  • opts (Hash)

    Options to pass through to Aws::DynamoDB::Client#transact_get_items, with the exception of the :transact_items array, which uses the #tfind_opts operation on your model class to provide extra metadata used to marshal your items after retrieval.

Options Hash (opts):

  • :transact_items (Array)

    A set of #tfind_opts results, such as those created by the usage example.

  • :client (Aws::DynamoDB::Client)

    Optionally, you can pass in your own client to use for the transaction calls.

Returns:

  • (OpenStruct)

    Structured like the client API response from #transact_get_items, except that the responses member contains Aws::Record items marshaled into the classes used to call #tfind_opts in each positional member. See the usage example.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/aws-record/record/transactions.rb', line 46

def transact_find(opts)
  opts = opts.dup
  client = opts.delete(:client) || dynamodb_client
  transact_items = opts.delete(:transact_items) # add nil check?
  model_classes = []
  client_transact_items = transact_items.map do |tfind_opts|
    model_class = tfind_opts.delete(:model_class)
    model_classes << model_class
    tfind_opts
  end
  request_opts = opts
  request_opts[:transact_items] = client_transact_items
  client_resp = client.transact_get_items(
    request_opts
  )
  responses = client_resp.responses
  index = -1
  ret = OpenStruct.new
  ret.consumed_capacity = client_resp.consumed_capacity
  ret.missing_items = []
  ret.responses = client_resp.responses.map do |item|
    index += 1
    if item.nil? || item.item.nil?
      missing_data = {
        model_class: model_classes[index],
        key: transact_items[index][:get][:key]
      }
      ret.missing_items << missing_data
      nil
    else
      # need to translate the item keys
      raw_item = item.item
      model_class = model_classes[index]
      new_item_opts = {}
      raw_item.each do |db_name, value|
        name = model_class.attributes.db_to_attribute_name(db_name)
        new_item_opts[name] = value
      end
      item = model_class.new(new_item_opts)
      item.clean!
      item
    end
  end
  ret
end

.transact_write(opts) ⇒ Object

Provides a way to pass in aws-record items into transactional writes, as well as adding the ability to run 'save' commands in a transaction while allowing aws-record to determine if a :put or :update operation is most appropriate. #transact_write supports 5 different transact item modes:

  • save: Behaves much like the #save operation on the item itself. If the keys are dirty, and thus it appears to be a new item, will create a :put operation with a conditional check on the item's existance. Note that you cannot bring your own conditional expression in this case. If you wish to force put or add your own conditional checks, use the :put operation.

  • put: Does a force put for the given item key and model.

  • update: Does an upsert for the given item.

  • delete: Deletes the given item.

  • check: Takes the result of #transact_check_expression, performing the specified check as a part of the transaction.

Examples:

Usage Example

class TableOne
  include Aws::Record
  string_attr :uuid, hash_key: true
  string_attr :body
end

class TableTwo
  include Aws::Record
  string_attr :hk, hash_key: true
  string_attr :rk, range_key: true
  string_attr :body
end

check_exp = TableOne.transact_check_expression(
  key: { uuid: "foo" },
  condition_expression: "size(#T) <= :v",
  expression_attribute_names: {
    "#T" => "body"
  },
  expression_attribute_values: {
    ":v" => 1024
  }
)
new_item = TableTwo.new(hk: "hk1", rk: "rk1", body: "Hello!")
update_item_1 = TableOne.find(uuid: "bar")
update_item_1.body = "Updated the body!"
put_item = TableOne.new(uuid: "foobar", body: "Content!")
update_item_2 = TableTwo.find(hk: "hk2", rk: "rk2")
update_item_2.body = "Update!"
delete_item = TableOne.find(uuid: "to_be_deleted")

Aws::Record::Transactions.transact_write(
  transact_items: [
    { check: check_exp },
    { save: new_item },
    { save: update_item_1 },
    {
       put: put_item,
       condition_expression: "attribute_not_exists(#H)",
       expression_attribute_names: { "#H" => "uuid" },
       return_values_on_condition_check_failure: "ALL_OLD"
    },
    { update: update_item_2 },
    { delete: delete_item }
  ]
)

Parameters:

  • opts (Hash)

    Options to pass through to Aws::DynamoDB::Client#transact_write_items with the exception of :transact_items array, which is transformed to use your item to populate the :key, :table_name, :item, and/or :update_expression parameters as appropriate. See the usage example for a comprehensive set of combinations.

Options Hash (opts):

  • :transact_items (Array)

    An array of hashes, accepting :save, :put, :delete, :update, and :check as specified.

  • :client (Aws::DynamoDB::Client)

    Optionally, you can specify a client to use for this transaction call. If not specified, the configured client for Aws::Record::Transactions is used.



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/aws-record/record/transactions.rb', line 169

def transact_write(opts)
  opts = opts.dup
  client = opts.delete(:client) || dynamodb_client
  dirty_items = []
  delete_items = []
  # fetch abstraction records
  transact_items = _transform_transact_write_items(
    opts.delete(:transact_items),
    dirty_items,
    delete_items
  )
  opts[:transact_items] = transact_items
  resp = client.transact_write_items(opts)
  # mark all items clean/destroyed as needed if we didn't raise an exception
  dirty_items.each { |i| i.clean! }
  delete_items.each { |i| i.instance_variable_get("@data").destroyed = true }
  resp
end