Class: StatelyDB::Transaction::Transaction

Inherits:
Object
  • Object
show all
Defined in:
lib/transaction/transaction.rb

Overview

Transaction coordinates sending requests and waiting for responses. Consumers should not need to interact with this class directly, but instead use the methods provided by the StatelyDB::CoreClient.

The example below demonstrates using a transaction, which accepts a block. The lines in the block are executed within the context of the transaction. The transaction is committed when the block completes successfully, OR is aborted if an exception is raised.

Examples:

result = client.transaction do |tx|
  key_path = StatelyDB::KeyPath.with('movie', 'The Shining')
  movie = tx.get(key_path:)
  tx.put(item: movie)
end

Defined Under Namespace

Classes: Result

Instance Method Summary collapse

Constructor Details

#initialize(stub:, store_id:, schema:) ⇒ Transaction

Initialize a new Transaction



48
49
50
51
52
53
54
55
56
# File 'lib/transaction/transaction.rb', line 48

def initialize(stub:, store_id:, schema:)
  @stub = stub
  @store_id = store_id
  @schema = schema
  @is_transaction_open = false

  # A queue of outbound requests
  @outgoing_requests = StatelyDB::Transaction::Queue.new
end

Instance Method Details

#begin_list(prefix, limit: 100, sort_property: nil, sort_direction: :ascending) ⇒ Array(Array<StatelyDB::Item>, ::Stately::Db::ListToken)

Begin listing Items from a StatelyDB Store at the given prefix.

Example:

client.data.transaction do |txn|
  (items, token) = txn.begin_list("/ItemType-identifier")
  (items, token) = txn.continue_list(token)
end


344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
# File 'lib/transaction/transaction.rb', line 344

def begin_list(prefix,
               limit: 100,
               sort_property: nil,
               sort_direction: :ascending)
  sort_direction = case sort_direction
                   when :ascending
                     0
                   else
                     1
                   end
  req = Stately::Db::TransactionRequest.new(
    begin_list: Stately::Db::TransactionBeginList.new(
      key_path_prefix: String(prefix),
      limit:,
      sort_property:,
      sort_direction:
    )
  )
  do_list_request_response(req)
end

#continue_list(token, continue_direction: :forward) ⇒ Array(Array<StatelyDB::Item>, ::Stately::Db::ListToken)

Continue listing Items from a StatelyDB Store using a token.

Example:

client.data.transaction do |txn|
  (items, token) = txn.begin_list("/foo")
  (items, token) = txn.continue_list(token)
end


376
377
378
379
380
381
382
383
384
385
386
# File 'lib/transaction/transaction.rb', line 376

def continue_list(token, continue_direction: :forward)
  continue_direction = continue_direction == :forward ? 0 : 1

  req = Stately::Db::TransactionRequest.new(
    continue_list: Stately::Db::TransactionContinueList.new(
      token_data: token.token_data,
      direction: continue_direction
    )
  )
  do_list_request_response(req)
end

#delete(*key_paths) ⇒ void

This method returns an undefined value.

Delete up to 50 Items from a StatelyDB Store at the given key_paths. Results are not returned until the transaction is committed and will be available in the Result object returned by commit.

Example:

client.data.transaction do |txn|
  txn.delete("/ItemType-identifier", "/ItemType-identifier2")
end


320
321
322
323
324
325
326
327
328
329
# File 'lib/transaction/transaction.rb', line 320

def delete(*key_paths)
  key_paths = Array(key_paths).flatten
  req = Stately::Db::TransactionRequest.new(
    delete_items: Stately::Db::TransactionDelete.new(
      deletes: key_paths.map { |key_path| Stately::Db::DeleteItem.new(key_path: String(key_path)) }
    )
  )
  request_only(req)
  nil
end

#get(key_path) ⇒ StatelyDB::Item, NilClass

Fetch Items from a StatelyDB Store at the given key_path. Note that Items need to exist before being retrieved inside a transaction.

Examples:

client.data.transaction do |txn|
  item = txn.get("/ItemType-identifier")
end

Raises:

  • (StatelyDB::Error::InvalidParameters)

    if the parameters are invalid

  • (StatelyDB::Error::NotFound)

    if the item is not found



190
191
192
193
194
195
# File 'lib/transaction/transaction.rb', line 190

def get(key_path)
  resp = get_batch(key_path)

  # Always return a single Item.
  resp.first
end

#get_batch(*key_paths) ⇒ Array<StatelyDB::Item>

Fetch a batch of up to 100 Items from a StatelyDB Store at the given key_paths. Note that Items need to exist before being retrieved inside a transaction.

key paths. Example:

client.data.transaction do |txn|
  items = txn.get_batch("/foo", "/bar")
end

Raises:

  • (StatelyDB::Error::InvalidParameters)

    if the parameters are invalid

  • (StatelyDB::Error::NotFound)

    if the item is not found



211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/transaction/transaction.rb', line 211

def get_batch(*key_paths)
  key_paths = Array(key_paths).flatten
  req = Stately::Db::TransactionRequest.new(
    get_items: Stately::Db::TransactionGet.new(
      gets: key_paths.map { |key_path| Stately::Db::GetItem.new(key_path: String(key_path)) }
    )
  )
  resp = request_response(req).get_results

  resp.items.map do |result|
    @schema.unmarshal_item(stately_item: result)
  end
end

#put(item, must_not_exist: false, overwrite_metadata_timestamps: false) ⇒ String, Integer

Put a single Item into a StatelyDB store. Results are not returned until the transaction is committed and will be available in the Result object returned by commit. An identifier for the item will be returned while inside the transaction block.

results.puts.each do |result|
  puts result.key_path
end

Examples:

results = client.data.transaction do |txn|
  txn.put(my_item)
end


252
253
254
255
256
257
# File 'lib/transaction/transaction.rb', line 252

def put(item,
        must_not_exist: false,
        overwrite_metadata_timestamps: false)
  resp = put_batch({ item:, must_not_exist:, overwrite_metadata_timestamps: })
  resp.first
end

#put_batch(*items) ⇒ Array<StatelyDB::UUID, String, Integer, NilClass>

Put a batch of up to 50 Items into a StatelyDB Store. Results are not returned until the transaction is committed and will be available in the Result object returned by commit. A list of identifiers for the items will be returned while inside the transaction block.

50 items.

results.puts.each do |result|
  puts result.key_path
end

Examples:

results = client.data.transaction do |txn|
  txn.put_batch(item1, item2)
end


275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/transaction/transaction.rb', line 275

def put_batch(*items)
  puts = Array(items).flatten.map do |input|
    if input.is_a?(Hash)
      item = input[:item]
      Stately::Db::PutItem.new(
        item: item.send("marshal_stately"),
        overwrite_metadata_timestamps: input[:overwrite_metadata_timestamps],
        must_not_exist: input[:must_not_exist]
      )
    else
      Stately::Db::PutItem.new(
        item: input.send("marshal_stately")
      )
    end
  end
  req = Stately::Db::TransactionRequest.new(
    put_items: Stately::Db::TransactionPut.new(
      puts:
    )
  )

  resp = request_response(req).put_ack
  resp.generated_ids.map do |generated_id|
    case generated_id.value
    when :bytes
      StatelyDB::UUID.valid_uuid?(generated_id.bytes) ? StatelyDB::UUID.parse(generated_id.bytes) : generated_id.bytes
    when :uint
      generated_id.uint
    else # rubocop:disable Style/EmptyElse
      # An empty identifier is sent in the transaction Put response if an initialValue is not set
      nil
    end
  end
end