Can you manage the commit / rollback transaction manually?

I would like to do something like this:

["START", "a", "b", "c", "STOP", "START", "d", "e", "STOP"].each do |message|
  if message == "START"
    Transaction.begin
  elsif message == "STOP"
    Transaction.commit if Transaction.active?
  else
    begin
      Message.create!(body: message)
    rescue
      Transaction.rollback
    end
  end
end

      

In short, I have a stream of "messages" and I would like to process parts of that stream.

Whenever "START" appears in the thread, a new transaction starts. When "STOP" appears, the transaction is committed.

I am struggling with transactions.

I can see that I can do ActiveRecord :: Base.transaction do ... end, but in this case it won't work unless I load everything, which is not possible due to streams.

I saw that in the ActiveRecord similar transaction manager that I could use ( https://github.com/rails/rails/blob/0d76ab9c6f01e6390ba8878a296ff9d3ac6b9aa8/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb ), but I do not was able to skip my tests against it.

I think part of the problem is also related to the interference of RSpec transactions, although disabling them did not solve the problem either.

Any help would be appreciated.

thank

+3


source to share


2 answers


I would do this:

messages.chunk {|value| value != 'START' && value != 'STOP'}.each do |is_data, bodies|
  if is_data
    Message.transaction do
      bodies.each {|body| Message.create(body: body)}
    end
  end
end

      



The first step is to use chunk

messages to group. This results in an array of pairs. If the first value of the pair is true, then the second value is an array of bodies, unless the bodies are true false. Thus, when reorganizing data, it is trivial to use the existing transaction method.

+2


source


you can manage the transaction like this

manager = ActiveRecord::Base.connection.transaction_manager
...
manager.begin_transaction
...
manager.commit_transaction
...
manager.rollback_transaction

      



or in your case

manager = ActiveRecord::Base.connection.transaction_manager
["START", "a", "b", "c", "STOP", "START", "d", "e", "STOP"].each do |message|
  if message == "START"
    manager.begin_transaction
  elsif message == "STOP"
    manager.commit_transaction
  else
    begin
      Message.create!(body: message)
    rescue
      manager.rollback_transaction
    end
  end
end

      

0


source







All Articles