Transações

Uma transação é um conjunto de operações em uma ou mais entidades. Todas as transações são atômicas, o que significa que elas nunca são aplicadas parcialmente. Ou todas as operações na transação são aplicadas ou nenhuma delas é aplicada.

Como usar transações

As transações expiram após 270 segundos ou se ficam inativas por 60 segundos.

Uma operação poderá falhar quando:

  • muitas modificações simultâneas forem tentadas na mesma entidade;
  • a transação exceder um limite de recursos;
  • o banco de dados do modo Datastore encontrar um erro interno.

Em todos esses casos, a API Datastore retorna um erro.

As transações são um recurso opcional. Usar transações para executar operações do banco de dados não é obrigatório.

Um aplicativo executa um conjunto de instruções e operações em uma única transação. Assim, caso alguma instrução ou operação gere uma exceção, não será aplicada nenhuma operação do banco de dados no conjunto. O aplicativo define as ações a serem executadas na transação.

Veja o snippet a seguir como realizar uma transação. A transação é uma transferência monetária de uma conta para outra.

C#

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

private void TransferFunds(Key fromKey, Key toKey, long amount)
{
    using (var transaction = _db.BeginTransaction())
    {
        var entities = transaction.Lookup(fromKey, toKey);
        entities[0]["balance"].IntegerValue -= amount;
        entities[1]["balance"].IntegerValue += amount;
        transaction.Update(entities);
        transaction.Commit();
    }
}

Go

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

type BankAccount struct {
	Balance int
}

const amount = 50
keys := []*datastore.Key{to, from}
tx, err := client.NewTransaction(ctx)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
accs := make([]BankAccount, 2)
if err := tx.GetMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.GetMulti: %v", err)
}
accs[0].Balance += amount
accs[1].Balance -= amount
if _, err := tx.PutMulti(keys, accs); err != nil {
	tx.Rollback()
	log.Fatalf("tx.PutMulti: %v", err)
}
if _, err = tx.Commit(); err != nil {
	log.Fatalf("tx.Commit: %v", err)
}

Java

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

void transferFunds(Key fromKey, Key toKey, long amount) {
  Transaction txn = datastore.newTransaction();
  try {
    List<Entity> entities = txn.fetch(fromKey, toKey);
    Entity from = entities.get(0);
    Entity updatedFrom =
        Entity.newBuilder(from).set("balance", from.getLong("balance") - amount).build();
    Entity to = entities.get(1);
    Entity updatedTo =
        Entity.newBuilder(to).set("balance", to.getLong("balance") + amount).build();
    txn.put(updatedFrom, updatedTo);
    txn.commit();
  } finally {
    if (txn.isActive()) {
      txn.rollback();
    }
  }
}

Node.js

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

async function transferFunds(fromKey, toKey, amount) {
  const transaction = datastore.transaction();
  await transaction.run();
  const results = await Promise.all([
    transaction.get(fromKey),
    transaction.get(toKey),
  ]);
  const accounts = results.map(result => result[0]);

  accounts[0].balance -= amount;
  accounts[1].balance += amount;

  transaction.save([
    {
      key: fromKey,
      data: accounts[0],
    },
    {
      key: toKey,
      data: accounts[1],
    },
  ]);

  return await transaction.commit();
}

PHP

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

/**
 * Update two entities in a transaction.
 *
 * @param string $fromKeyId
 * @param string $toKeyId
 * @param int $amount
 * @param string $namespaceId
 */
function transfer_funds(
    string $fromKeyId,
    string $toKeyId,
    int $amount,
    string $namespaceId = null
) {
    $datastore = new DatastoreClient(['namespaceId' => $namespaceId]);
    $transaction = $datastore->transaction();
    $fromKey = $datastore->key('Account', $fromKeyId);
    $toKey = $datastore->key('Account', $toKeyId);
    // The option 'sort' is important here, otherwise the order of the result
    // might be different from the order of the keys.
    $result = $transaction->lookupBatch([$fromKey, $toKey], ['sort' => true]);
    if (count($result['found']) != 2) {
        $transaction->rollback();
    }
    $fromAccount = $result['found'][0];
    $toAccount = $result['found'][1];
    $fromAccount['balance'] -= $amount;
    $toAccount['balance'] += $amount;
    $transaction->updateBatch([$fromAccount, $toAccount]);
    $transaction->commit();
}

Python

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

def transfer_funds(client, from_key, to_key, amount):
    with client.transaction():
        from_account = client.get(from_key)
        to_account = client.get(to_key)

        from_account["balance"] -= amount
        to_account["balance"] += amount

        client.put_multi([from_account, to_account])

Ruby

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Para manter nossos exemplos mais sucintos, às vezes omitimos rollback se a transação falha. Em código de produção, é importante garantir que cada transação seja executada explicitamente ou revertida.

O que pode ser feito em uma transação

As transações podem consultar ou procurar qualquer número de entidades. O tamanho máximo de uma transação é de 10 MiB. É possível usar uma transação de leitura/gravação ou uma transação somente leitura.

Isolamento e consistência

Bancos de dados do modo Datastore implementam o isolamento serializável. Os dados lidos ou modificados por uma transação não podem ser modificados simultaneamente.

As consultas e pesquisas de uma transação analisam um instantâneo consistente do estado do banco de dados. Esse instantâneo contém o efeito de todas as transações e grava o que foi concluído antes do início da transação.

A visualização desse instantâneo consistente também se estende a leituras após gravações dentro de transações. Diferentemente da maioria dos bancos de dados, as consultas e pesquisas dentro de uma transação do Cloud Datastore não exibem os resultados de gravações anteriores dentro dessa transação. Especificamente, se uma entidade é modificada ou excluída em uma transação, uma consulta ou pesquisa retorna a versão original da entidade no início da transação ou nada, se a entidade não existia.

Fora das transações, as consultas e pesquisas também têm isolamento serializável.

Modos de simultaneidade

O Firestore no modo Datastore oferece suporte a três modos de simultaneidade. O modo de simultaneidade é uma configuração de banco de dados que determina como as transações simultâneas interagem. Você pode selecionar um dos seguintes modos de simultaneidade:

  • Pessimista

    Transações de leitura/gravação usam bloqueios de leitor/gravador para implementar o isolamento e a serialização. Quando duas ou mais transações de leitura/gravação simultâneas leem ou gravam os mesmos dados, o bloqueio retido por uma transação pode atrasar as outras transações. Se sua transação não exigir gravações, será possível melhorar o desempenho e evitar a contenção com outras transações usando uma transação somente leitura. Transações somente leitura não exigem bloqueios.

    Os bancos de dados do Firestore no modo Datastore usam o modo de simultaneidade pessimista por padrão.

  • Otimista

    Quando duas ou mais transações de leitura/gravação simultâneas leem ou gravam os mesmos dados, somente a primeira transação que faz o commit das mudanças é bem-sucedida. Outras transações que executam gravações falham na confirmação.

  • Otimismo com grupos de entidades

    Use esse modo de simultaneidade somente se o app depender da semântica transacional do grupo de entidades do Cloud Datastore legados. Esse modo de simultaneidade impõe limites adicionais às transações:

    • As transações são limitadas a 25 grupos de entidades.
    • As gravações em um grupo de entidades são limitadas a uma por segundo.
    • As consultas em transações precisam ser consultas de ancestral.

    Para remover as limitações de consulta, transação e taxa de transferência de gravação de OPTIMISTIC_WITH_ENTITY_GROUPS, mude o modo de simultaneidade do projeto para "Otimista". Para garantir que essa mudança seja compatível com seu projeto:

    1. Crie um projeto de teste no Firestore no modo Datastore.

    2. Mude o modo de concorrência do projeto de teste para OPTIMISTIC. Emita uma solicitação HTTP PATCH, conforme demonstrado abaixo.

    3. Execute testes no projeto de teste para garantir que a carga de trabalho tenha o desempenho esperado sem grupos de entidades.

    4. Mude o modo de simultaneidade do seu projeto principal de OPTIMISTIC_WITH_ENTITY_GROUPS para OPTIMISTIC.

Conferir o modo de simultaneidade

Use o recurso REST projects.databases do Firestore para conferir o modo de simultaneidade do seu banco de dados:

curl -X GET -H "Authorization: Bearer "$(gcloud auth print-access-token) \
"https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases"

Mudar o modo de simultaneidade

Para mudar o modo de simultaneidade do banco de dados, envie uma solicitação PATCH para o recurso REST projects.databases do Firestore:

curl --request PATCH \
--header "Authorization: Bearer "$(gcloud auth print-access-token) \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{"concurrencyMode":"CONCURRENCY_MODE"}' \
"https://firestore.googleapis.com/v1/projects/PROJECT_ID/databases/(default)?updateMask=concurrencyMode"

em que:

  • CONCURRENCY_MODE é PESSIMISTIC, OPTIMISTIC ou OPTIMISTIC_WITH_ENTITY_GROUPS;
  • PROJECT_ID é o ID do seu projeto do Google Cloud.

Usos das transações

Um dos usos das transações é a atualização de uma entidade com um novo valor de propriedade relativo ao seu valor atual. O exemplo transferFunds acima faz isso para duas entidades, retirando dinheiro de uma conta e transferindo-o para outra. A API Datastore não tenta repetir transações automaticamente, mas é possível adicionar sua própria lógica para repeti-las, por exemplo, para lidar com conflitos quando outra solicitação atualiza a mesma entidade ao mesmo tempo.

C#

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

/// <summary>
/// Retry the action when a Grpc.Core.RpcException is thrown.
/// </summary>
private T RetryRpc<T>(Func<T> action)
{
    List<Grpc.Core.RpcException> exceptions = null;
    var delayMs = _retryDelayMs;
    for (int tryCount = 0; tryCount < _retryCount; ++tryCount)
    {
        try
        {
            return action();
        }
        catch (Grpc.Core.RpcException e)
        {
            if (exceptions == null)
                exceptions = new List<Grpc.Core.RpcException>();
            exceptions.Add(e);
        }
        System.Threading.Thread.Sleep(delayMs);
        delayMs *= 2;  // Exponential back-off.
    }
    throw new AggregateException(exceptions);
}

private void RetryRpc(Action action)
{
    RetryRpc(() => { action(); return 0; });
}

[Fact]
public void TestTransactionalRetry()
{
    int tryCount = 0;
    var keys = UpsertBalances();
    RetryRpc(() =>
    {
        using (var transaction = _db.BeginTransaction())
        {
            TransferFunds(keys[0], keys[1], 10, transaction);
            // Insert a conflicting transaction on the first try.
            if (tryCount++ == 0)
                TransferFunds(keys[1], keys[0], 5);
            transaction.Commit();
        }
    });
    Assert.Equal(2, tryCount);
}

Go

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

type BankAccount struct {
	Balance int
}

const amount = 50
_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	keys := []*datastore.Key{to, from}
	accs := make([]BankAccount, 2)
	if err := tx.GetMulti(keys, accs); err != nil {
		return err
	}
	accs[0].Balance += amount
	accs[1].Balance -= amount
	_, err := tx.PutMulti(keys, accs)
	return err
})

Java

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

int retries = 5;
while (true) {
  try {
    transferFunds(fromKey, toKey, 10);
    break;
  } catch (DatastoreException e) {
    if (retries == 0) {
      throw e;
    }
    --retries;
  }
}
// Retry handling can also be configured and automatically applied using google-cloud-java.

Node.js

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

async function transferFundsWithRetry() {
  const maxTries = 5;

  async function tryRequest(currentAttempt, delay) {
    try {
      await transferFunds(fromKey, toKey, 10);
    } catch (err) {
      if (currentAttempt <= maxTries) {
        // Use exponential backoff
        setTimeout(async () => {
          await tryRequest(currentAttempt + 1, delay * 2);
        }, delay);
      }
      throw err;
    }
  }

  await tryRequest(1, 100);
}

PHP

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

$retries = 5;
for ($i = 0; $i < $retries; $i++) {
    try {
        require_once __DIR__ . '/transfer_funds.php';
        transfer_funds($fromKeyId, $toKeyId, 10, $namespaceId);
    } catch (\Google\Cloud\Core\Exception\ConflictException $e) {
        // if $i >= $retries, the failure is final
        continue;
    }
    // Succeeded!
    break;
}

Python

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import google.cloud.exceptions

for _ in range(5):
    try:
        transfer_funds(client, account1.key, account2.key, 50)
        break
    except google.cloud.exceptions.Conflict:
        continue
else:
    print("Transaction failed.")

Ruby

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

(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

Isso requer uma transação porque o valor de balance em uma entidade pode ser atualizado por outro usuário após esse código buscar o objeto, mas antes de salvar o objeto modificado. Sem uma transação, a solicitação do usuário usa o valor de balance antes da atualização do outro usuário, e a gravação substitui o novo valor. Com uma transação, o aplicativo é informado sobre a atualização.

Outro uso comum das transações é buscar uma entidade com uma chave nomeada, ou criá-la, caso ela ainda não exista (este exemplo é baseado no exemplo da TaskList de como criar uma entidade):

C#

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Entity task;
using (var transaction = _db.BeginTransaction())
{
    task = transaction.Lookup(_sampleTask.Key);
    if (task == null)
    {
        transaction.Insert(_sampleTask);
        transaction.Commit();
    }
}

Go

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

_, err := client.RunInTransaction(ctx, func(tx *datastore.Transaction) error {
	var task Task
	if err := tx.Get(key, &task); err != datastore.ErrNoSuchEntity {
		return err
	}
	_, err := tx.Put(key, &Task{
		Category:    "Personal",
		Done:        false,
		Priority:    4,
		Description: "Learn Cloud Datastore",
	})
	return err
})

Java

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Entity task;
Transaction txn = datastore.newTransaction();
try {
  task = txn.get(taskKey);
  if (task == null) {
    task = Entity.newBuilder(taskKey).build();
    txn.put(task);
    txn.commit();
  }
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

async function getOrCreate(taskKey, taskData) {
  const taskEntity = {
    key: taskKey,
    data: taskData,
  };
  const transaction = datastore.transaction();

  try {
    await transaction.run();
    const [task] = await transaction.get(taskKey);
    if (task) {
      // The task entity already exists.
      await transaction.rollback();
    } else {
      // Create the task entity.
      transaction.save(taskEntity);
      await transaction.commit();
    }
    return taskEntity;
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

$transaction = $datastore->transaction();
$entity = $transaction->lookup($task->key());
if ($entity === null) {
    $entity = $transaction->insert($task);
    $transaction->commit();
}

Python

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

import datetime

with client.transaction():
    key = client.key(
        "Task", datetime.datetime.now(tz=datetime.timezone.utc).isoformat()
    )

    task = client.get(key)

    if not task:
        task = datastore.Entity(key)
        task.update({"description": "Example task"})
        client.put(task)

    return task

Ruby

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

Como antes, uma transação é necessária para manipular o caso quando outro usuário estiver tentando criar ou atualizar uma entidade com o mesmo ID de string. Sem uma transação, se a entidade não existir e dois usuários tentarem criá-la, o segundo substituirá o primeiro sem saber o que aconteceu.

Quando uma transação falha, é possível fazer com que o app repita a transação até ter êxito, ou é possível deixar que os usuários lidem com o erro propagando-o até o nível de interface do usuário do app. Não é necessário criar um ciclo de repetições em torno de cada transação.

Transações somente leitura

Por fim, é possível usar uma transação para ler um instantâneo consistente do banco de dados. Isso pode ser útil quando forem necessárias várias leituras para renderizar uma página ou para exportar dados que precisam ser consistentes. É possível criar uma transação somente leitura para esses casos.

As transações somente leitura não podem modificar entidades, mas, em contrapartida, não entram em conflito com outras transações e não precisam ser repetidas. Se alguma transação regular de leitura/gravação executar apenas leituras, essa transação pode entrar em conflito com transações que modificam os mesmos dados.

C#

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API C# do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Entity taskList;
IReadOnlyList<Entity> tasks;
using (var transaction = _db.BeginTransaction(TransactionOptions.CreateReadOnly()))
{
    taskList = transaction.Lookup(taskListKey);
    var query = new Query("Task")
    {
        Filter = Filter.HasAncestor(taskListKey)
    };
    tasks = transaction.RunQuery(query).Entities;
    transaction.Commit();
}

Go

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Go do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

tx, err := client.NewTransaction(ctx, datastore.ReadOnly)
if err != nil {
	log.Fatalf("client.NewTransaction: %v", err)
}
defer tx.Rollback() // Transaction only used for read.

ancestor := datastore.NameKey("TaskList", "default", nil)
query := datastore.NewQuery("Task").Ancestor(ancestor).Transaction(tx)
var tasks []Task
_, err = client.GetAll(ctx, query, &tasks)

Java

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Java do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

Entity taskList;
QueryResults<Entity> tasks;
Transaction txn =
    datastore.newTransaction(
        TransactionOptions.newBuilder().setReadOnly(ReadOnly.newBuilder().build()).build());
try {
  taskList = txn.get(taskListKey);
  Query<Entity> query =
      Query.newEntityQueryBuilder()
          .setKind("Task")
          .setFilter(PropertyFilter.hasAncestor(taskListKey))
          .build();
  tasks = txn.run(query);
  txn.commit();
} finally {
  if (txn.isActive()) {
    txn.rollback();
  }
}

Node.js

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Node.js do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

async function getTaskListEntities() {
  const transaction = datastore.transaction({readOnly: true});
  try {
    const taskListKey = datastore.key(['TaskList', 'default']);

    await transaction.run();
    const [taskList] = await transaction.get(taskListKey);
    const query = datastore.createQuery('Task').hasAncestor(taskListKey);
    const [taskListEntities] = await transaction.runQuery(query);
    await transaction.commit();
    return [taskList, taskListEntities];
  } catch (err) {
    await transaction.rollback();
  }
}

PHP

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API PHP do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

$transaction = $datastore->readOnlyTransaction();
$taskListKey = $datastore->key('TaskList', 'default');
$query = $datastore->query()
    ->kind('Task')
    ->hasAncestor($taskListKey);
$result = $transaction->runQuery($query);
$taskListEntities = [];
$num = 0;
/* @var Entity $task */
foreach ($result as $task) {
    $taskListEntities[] = $task;
    $num += 1;
}

Python

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Python do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

from google.cloud import datastore

# For help authenticating your client, visit
# https://cloud.google.com/docs/authentication/getting-started
client = datastore.Client()

with client.transaction(read_only=True):
    task_list_key = client.key("TaskList", "default")

    task_list = client.get(task_list_key)

    query = client.query(kind="Task", ancestor=task_list_key)
    tasks_in_list = list(query.fetch())

    return task_list, tasks_in_list

Ruby

Para saber como instalar e usar a biblioteca de cliente do Cloud Datastore, consulte Bibliotecas de cliente do Cloud Datastore. Para mais informações, consulte a documentação de referência da API Ruby do Cloud Datastore.

Para autenticar no Cloud Datastore, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.

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

A seguir