Class: Google::Cloud::Datastore::Transaction

Inherits:
Dataset
  • Object
show all
Defined in:
lib/google/cloud/datastore/transaction.rb

Overview

Transaction

Special Connection instance for running transactions.

See Dataset#transaction

Examples:

Transactional update:

def transfer_funds from_key, to_key, amount
  datastore.transaction do |tx|
    from = tx.find from_key
    from["balance"] -= amount
    to = tx.find to_key
    to["balance"] += amount
    tx.save from, to
  end
end

Retry logic using the transactional update example above:

(1..5).each do |i|
  begin
    return transfer_funds from_key, to_key, amount
  rescue Google::Cloud::Error => e
    raise e if i == 5
  end
end

Transactional read:

task_list_key = datastore.key "TaskList", "default"
datastore.transaction do |tx|
  task_list = tx.find task_list_key
  query = tx.query("Task").ancestor(task_list)
  tasks_in_list = tx.run query
end

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Dataset

#allocate_ids, #entity, #gql, #key, #project, #query, #transaction

Instance Attribute Details

#idObject (readonly)

Returns the value of attribute id



58
59
60
# File 'lib/google/cloud/datastore/transaction.rb', line 58

def id
  @id
end

Instance Method Details

#commit {|commit| ... } ⇒ Object

Commits a transaction.

Examples:

require "google/cloud"

gcloud = Google::Cloud.new
datastore = gcloud.datastore

task = datastore.entity "Task" do |t|
  t["type"] = "Personal"
  t["done"] = false
  t["priority"] = 4
  t["description"] = "Learn Cloud Datastore"
end

tx = datastore.transaction
begin
  if tx.find(task.key).nil?
    tx.save task
  end
  tx.commit
rescue
  tx.rollback
end

Commit can be passed a block, same as Dataset#commit:

require "google/cloud"

gcloud = Google::Cloud.new
datastore = gcloud.datastore

tx = datastore.transaction
begin
  tx.commit do |c|
    c.save task1, task2
    c.delete entity1, entity2
  end
rescue
  tx.rollback
end

Yields:

  • (commit)

    an optional block for making changes

Yield Parameters:

  • commit (Commit)

    The object that changes are made on



300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/google/cloud/datastore/transaction.rb', line 300

def commit
  fail TransactionError,
       "Cannot commit when not in a transaction." if @id.nil?

  yield @commit if block_given?

  ensure_service!

  commit_res = service.commit @commit.mutations, transaction: @id
  entities = @commit.entities
  returned_keys = commit_res.mutation_results.map(&:key)
  returned_keys.each_with_index do |key, index|
    next if entities[index].nil?
    entities[index].key = Key.from_grpc(key) unless key.nil?
  end
  # Make sure all entity keys are frozen so all show as persisted
  entities.each { |e| e.key.freeze unless e.persisted? }
  true
end

#delete(*entities_or_keys) ⇒ Object

Remove entities in a transaction.

Examples:

datastore.transaction do |tx|
  if tx.find(task_list.key).nil?
    tx.delete task1, task2
  end
end


155
156
157
158
159
# File 'lib/google/cloud/datastore/transaction.rb', line 155

def delete *entities_or_keys
  @commit.delete(*entities_or_keys)
  # Do not delete yet
  true
end

#find(key_or_kind, id_or_name = nil) ⇒ Google::Cloud::Datastore::Entity? Also known as: get

Retrieve an entity by providing key information. The lookup is run within the transaction.

Examples:

Finding an entity with a key:

task_key = datastore.key "Task", "sampleTask"
task = datastore.find task_key

Finding an entity with a kind and id/name:

task = datastore.find "Task", "sampleTask"

Parameters:

  • key_or_kind (Key, String)

    A Key object or kind string value.

Returns:



176
177
178
179
180
181
182
# File 'lib/google/cloud/datastore/transaction.rb', line 176

def find key_or_kind, id_or_name = nil
  key = key_or_kind
  unless key.is_a? Google::Cloud::Datastore::Key
    key = Key.new key_or_kind, id_or_name
  end
  find_all(key).first
end

#find_all(*keys) ⇒ Google::Cloud::Datastore::Dataset::LookupResults Also known as: lookup

Retrieve the entities for the provided keys. The lookup is run within the transaction.

Examples:

gcloud = Google::Cloud.new
datastore = gcloud.datastore
task_key1 = datastore.key "Task", 123456
task_key2 = datastore.key "Task", 987654
tasks = datastore.find_all task_key1, task_key2

Parameters:

  • keys (Key)

    One or more Key objects to find records for.

Returns:



200
201
202
203
204
205
# File 'lib/google/cloud/datastore/transaction.rb', line 200

def find_all *keys
  ensure_service!
  lookup_res = service.lookup(*Array(keys).flatten.map(&:to_grpc),
                              transaction: @id)
  LookupResults.from_grpc lookup_res, service, nil, @id
end

#insert(*entities) ⇒ Object

Insert entities in a transaction. An InvalidArgumentError will raised if the entities cannot be inserted.

Examples:

Transactional insert:

task_key = datastore.key "Task", "sampleTask"

task = nil
datastore.transaction do |tx|
  task = tx.find task_key
  if task.nil?
    task = datastore.entity task_key do |t|
      t["type"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end
    tx.insert task
  end
end


117
118
119
120
121
# File 'lib/google/cloud/datastore/transaction.rb', line 117

def insert *entities
  @commit.insert(*entities)
  # Do not insert yet
  entities
end

#reset!Object

Reset the transaction. #start must be called afterwards.



358
359
360
361
# File 'lib/google/cloud/datastore/transaction.rb', line 358

def reset!
  @id = nil
  @commit = Commit.new
end

#rollbackObject

Rolls a transaction back.

Examples:

require "google/cloud"

gcloud = Google::Cloud.new
datastore = gcloud.datastore

task = datastore.entity "Task" do |t|
  t["type"] = "Personal"
  t["done"] = false
  t["priority"] = 4
  t["description"] = "Learn Cloud Datastore"
end

tx = datastore.transaction
begin
  if tx.find(task.key).nil?
    tx.save task
  end
  tx.commit
rescue
  tx.rollback
end


345
346
347
348
349
350
351
352
353
# File 'lib/google/cloud/datastore/transaction.rb', line 345

def rollback
  if @id.nil?
    fail TransactionError, "Cannot rollback when not in a transaction."
  end

  ensure_service!
  service.rollback @id
  true
end

#run(query, namespace: nil) ⇒ Google::Cloud::Datastore::Dataset::QueryResults Also known as: run_query

Retrieve entities specified by a Query. The query is run within the transaction.

Examples:

query = datastore.query("Task").
  where("done", "=", false)
datastore.transaction do |tx|
  tasks = tx.run query
end

Run the query within a namespace with the namespace option:

query = Google::Cloud::Datastore::Query.new.kind("Task").
  where("done", "=", false)
datastore.transaction do |tx|
  tasks = tx.run query, namespace: "ns~todo-project"
end

Parameters:

  • query (Query)

    The Query object with the search criteria.

  • namespace (String)

    The namespace the query is to run within.

Returns:



231
232
233
234
235
236
237
238
239
240
# File 'lib/google/cloud/datastore/transaction.rb', line 231

def run query, namespace: nil
  ensure_service!
  unless query.is_a?(Query) || query.is_a?(GqlQuery)
    fail ArgumentError, "Cannot run a #{query.class} object."
  end
  query_res = service.run_query query.to_grpc, namespace,
                                transaction: @id
  QueryResults.from_grpc query_res, service, namespace,
                         query.to_grpc.dup
end

#save(*entities) ⇒ Object Also known as: upsert

Persist entities in a transaction.

Examples:

Transactional get or create:

task_key = datastore.key "Task", "sampleTask"

task = nil
datastore.transaction do |tx|
  task = tx.find task_key
  if task.nil?
    task = datastore.entity task_key do |t|
      t["type"] = "Personal"
      t["done"] = false
      t["priority"] = 4
      t["description"] = "Learn Cloud Datastore"
    end
    tx.save task
  end
end


89
90
91
92
93
# File 'lib/google/cloud/datastore/transaction.rb', line 89

def save *entities
  @commit.save(*entities)
  # Do not save yet
  entities
end

#startObject Also known as: begin_transaction

Begins a transaction. This method is run when a new Transaction is created.



246
247
248
249
250
251
252
# File 'lib/google/cloud/datastore/transaction.rb', line 246

def start
  fail TransactionError, "Transaction already opened." unless @id.nil?

  ensure_service!
  tx_res = service.begin_transaction
  @id = tx_res.transaction
end

#update(*entities) ⇒ Object

Update entities in a transaction. An InvalidArgumentError will raised if the entities cannot be updated.

Examples:

Transactional update:

task_key = datastore.key "Task", "sampleTask"

task = nil
datastore.transaction do |tx|
  task = tx.find task_key
  if task
    task["done"] = true
    tx.update task
  end
end


139
140
141
142
143
# File 'lib/google/cloud/datastore/transaction.rb', line 139

def update *entities
  @commit.update(*entities)
  # Do not update yet
  entities
end