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

See Also:

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from Dataset

#allocate_ids, #entity, #gql, #key, #project_id, #query, #read_only_transaction, #transaction

Instance Attribute Details

#idString (readonly)

The identifier of the transaction.

Returns:

  • (String)

    the current value of id



46
47
48
# File 'lib/google/cloud/datastore/transaction.rb', line 46

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



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
# File 'lib/google/cloud/datastore/transaction.rb', line 322

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

  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


161
162
163
164
165
# File 'lib/google/cloud/datastore/transaction.rb', line 161

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:



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

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:



216
217
218
219
220
221
# File 'lib/google/cloud/datastore/transaction.rb', line 216

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


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

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

#reset!Object

Reset the transaction. #start must be called afterwards.



380
381
382
383
# File 'lib/google/cloud/datastore/transaction.rb', line 380

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


367
368
369
370
371
372
373
374
375
# File 'lib/google/cloud/datastore/transaction.rb', line 367

def rollback
  if @id.nil?
    raise 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

datastore.transaction do |tx|
  query = datastore.query("Task")
  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: "example-ns"
end

Parameters:

  • query (Query)

    The Query object with the search criteria.

  • namespace (String) (defaults to: nil)

    The namespace the query is to run within.

Returns:



254
255
256
257
258
259
260
261
262
263
# File 'lib/google/cloud/datastore/transaction.rb', line 254

def run query, namespace: nil
  ensure_service!
  unless query.is_a?(Query) || query.is_a?(GqlQuery)
    raise 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


83
84
85
86
87
# File 'lib/google/cloud/datastore/transaction.rb', line 83

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.

Raises:



269
270
271
272
273
274
275
276
# File 'lib/google/cloud/datastore/transaction.rb', line 269

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

  ensure_service!
  tx_res = service.begin_transaction \
    previous_transaction: @previous_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


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

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