Menu Docs
Página inicial do Docs
/ / /
Mongoid
/

Transações

Nesta página

  • Usando transação
  • API de nível superior
  • API de nível inferior

Versão 4.0 do servidor MongoDB introduz transações multidocumento. (As atualizações de vários campos em um único documento são atômicas em todas as versões do MongoDB). As transações exigem uma topologia não autônoma do MongoDB e driver Ruby versão 2.6 ou superior. Uma API de transação de nível superior requer a versão Mongoide 9.0 ou superior, enquanto uma API de nível inferior exige a versão Mongoid 6.4 ou superior.

Uma transação pode ser iniciada chamando o método transaction em uma instância de uma classe de documento Mongoid, em uma classe de documento Mongoid ou no módulo Mongoid :

Band.transaction do
Band.create(title: 'Led Zeppelin')
end
band = Band.create(title: 'Deep Purple')
band.transaction do
band.active = false
band.save!
end
Mongoid.transaction do
band.destroy
end

Quando o método transaction é chamado, o Mongoid faz o seguinte:

  • cria uma sessão em um cliente que é usado pelo receptor da chamada de método transaction ;

  • inicia uma transação na sessão;

  • executa o bloco fornecido;

  • confirma a transação se nenhuma exceção gerada no bloco;

    • chama after_commit retornos de chamada para todos os objetos modificados dentro da transação

  • aborta a transação se uma exceção for gerada no bloco;

    • chama after_rollback retornos de chamada para todos os objetos modificados dentro da transação

  • fecha a sessão

Observação

Como uma transação está vinculada a um cliente específico, _only_ operações no mesmo cliente estarão no escopo da transação. Portanto, é recomendável que somente objetos que usam o mesmo cliente sejam usados dentro do bloco de método transaction .

class Author
include Mongoid::Document
store_in client: :encrypted_client
end
class User
include Mongoid::Document
store_in client: :encrypted_client
end
class Article
include Mongoid::Document
# This class uses the :default client
end
# Transaction is started on the :encrypted_client
Author.transaction do
# This operation uses the same client, so it is in the transaction
Author.create!
# This operation also uses the same client, so it is in the transaction
User.create!
# This operation uses a different client, so it is NOT in the transaction
Article.create!
end

Observação

Quando o método transaction é chamado no módulo Mongoid , a transação é criada usando o cliente :default .

Qualquer exceção gerada dentro do bloco de método transaction aborta a transação. Normalmente, a exceção criada é passada, exceto para Mongoid::Errors::Rollback. Este erro deve ser gerado se você quiser abortar explicitamente a transação sem passar uma exceção.

A API de transação introduz duas novas chamadas de resposta - after_commit e after_rollback.

after_commit a chamada de resposta é acionada para um objeto que foi criado, salvo ou destruído:

  • depois que a transação for confirmada se o objeto foi modificado dentro da transação;

  • depois que o objeto tiver sido persistente se o objeto tiver sido modificado fora de uma transação.

Observação

Em qualquer caso, a chamada de resposta after_commit é acionada somente depois que todas as outras chamadas de resposta foram executadas com sucesso. Portanto, se o objeto for modificado sem uma transação, é possível que o objeto tenha persistido, mas a chamada de resposta after_commit não tenha sido acionada (por exemplo, uma exceção gerada na chamada de resposta after_save ).

after_rollback a chamada de resposta é acionada para um objeto que foi criado, salvo ou destruído dentro de uma transação se a transação tiver sido cancelada. after_rollback nunca é acionado sem uma transação.

Para iniciar uma transação, o aplicativo deve ter umasessão .

Uma transação pode ser iniciada chamando o método start_transaction em uma sessão, que pode ser obtida chamando o método with_session em uma classe ou instância de modelo:

class Person
include Mongoid::Document
end
Person.with_session do |session|
session.start_transaction
end
person = Person.new
person.with_session do |session|
session.start_transaction
end

Também é possível especificar a referência de leitura, referência de escrita e preferência de leitura ao iniciar uma transação:

Person.with_session do |session|
session.start_transaction(
read_concern: {level: :majority},
write_concern: {w: 3},
read: {mode: :primary})
end

Uma transação pode ser confirmada ou abortada. Os métodos correspondentes para fazer isso são commit_transaction e abort_transaction, novamente na instância da sessão:

Person.with_session do |session|
session.commit_transaction
end
Person.with_session do |session|
session.abort_transaction
end

Se uma sessão terminar com uma transação aberta, a transação será cancelada.

A confirmação da transação pode ser repetida se falhar. Aqui está o código Ruby para fazer isso:

begin
session.commit_transaction
rescue Mongo::Error => e
if e.label?(Mongo::Error::UNKNOWN_TRANSACTION_COMMIT_RESULT_LABEL)
retry
else
raise
end
end

Observe que, para realizar operações dentro da transação, as operações devem usar o mesmo cliente em que a sessão foi iniciada. Por padrão, todas as operações serão feitas no cliente padrão:

class Person
include Mongoid::Document
end
class Post
include Mongoid::Document
end
Person.with_session do |s|
s.start_transaction
Person.create!
Person.create!
Post.create!
s.commit_transaction
end

Para usar explicitamente um cliente diferente, use o método with :

Post.with(client: :other) do
Person.with(client: :other) do
Person.with_session do |s|
s.start_transaction
Person.create!
Person.create!
Post.create!
s.commit_transaction
end
end
end

Voltar

Sessões