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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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

Transactional read:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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



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

def id
  @id
end

Instance Method Details

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

Commits a transaction.

Examples:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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/datastore"

datastore = Google::Cloud::Datastore.new

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

Yields:

  • (commit)

    an optional block for making changes

Yield Parameters:

  • commit (Commit)

    The object that changes are made on



331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
# File 'lib/google/cloud/datastore/transaction.rb', line 331

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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


170
171
172
173
174
# File 'lib/google/cloud/datastore/transaction.rb', line 170

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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

Finding an entity with a kind and id/name:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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

Parameters:

  • key_or_kind (Key, String)

    A Key object or kind string value.

Returns:



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

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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:



225
226
227
228
229
230
# File 'lib/google/cloud/datastore/transaction.rb', line 225

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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


124
125
126
127
128
# File 'lib/google/cloud/datastore/transaction.rb', line 124

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

#reset!Object

Reset the transaction. #start must be called afterwards.



388
389
390
391
# File 'lib/google/cloud/datastore/transaction.rb', line 388

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

#rollbackObject

Rolls a transaction back.

Examples:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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


375
376
377
378
379
380
381
382
383
# File 'lib/google/cloud/datastore/transaction.rb', line 375

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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:



264
265
266
267
268
269
270
271
272
273
# File 'lib/google/cloud/datastore/transaction.rb', line 264

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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


92
93
94
95
96
# File 'lib/google/cloud/datastore/transaction.rb', line 92

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.



279
280
281
282
283
284
285
# File 'lib/google/cloud/datastore/transaction.rb', line 279

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:

require "google/cloud/datastore"

datastore = Google::Cloud::Datastore.new

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


150
151
152
153
154
# File 'lib/google/cloud/datastore/transaction.rb', line 150

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