Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Database-safe Concurrency in ROR

Trying to figure out how concurrency is dealt with in Ruby On Rails.

How do I get a segment of code to lock on lines in the database and force rollbacks when needed?

More specificly, Is there a way to force a certain segment of code to complete totally and if not rollback? I'm looking to add history to transactions in my project and I don't want transactions to commit without the history being saved so if the server falls between the two actions (saving the transaction and saving the history) the database may go into an illegal state.

like image 664
Nachshon Schwartz Avatar asked Oct 24 '11 20:10

Nachshon Schwartz


People also ask

Is Ruby good for concurrency?

Ruby Fibers let you achieve cooperative concurrency within a single thread. This means that fibers are not preempted and the program itself must do the scheduling. Because the programmer controls when fibers start and stop, it is much easier to avoid race conditions.

Can rails handle concurrent requests?

1 Automatic ConcurrencyRails automatically allows various operations to be performed at the same time. When using a threaded web server, such as the default Puma, multiple HTTP requests will be served simultaneously, with each request provided its own controller instance.

Is Ruby on Rails thread-safe?

None of the core data structures (except for Queue) in Ruby are thread-safe. The structures are mutable, and when shared between threads, there are no guarantees the threads won't overwrite each others' changes. Fortunately, this is rarely the case in Rails apps.

Is Ruby on Rails multithreaded?

Dissecting Ruby on Rails 5 - Become a Professional Developer Often on a single CPU machine, multiple threads are not actually executed in parallel, but parallelism is simulated by interleaving the execution of the threads. Ruby makes it easy to write multi-threaded programs with the Thread class.


2 Answers

You want to look at ActiveRecord Transactions and Pessimistic Locking.

Account.transaction do
  account = Account.find(account_id)
  account.lock!

  if account.balance >= 100
    account.balance -= 100
    account.save
  end
end
like image 101
Douglas F Shearer Avatar answered Sep 30 '22 15:09

Douglas F Shearer


Yes, you have a way of implementing a transaction in Rails. An example:

YourModel.transaction do
  rec1.save!
  rec2.save!
end

More info here

like image 31
Ricardo Acras Avatar answered Sep 30 '22 14:09

Ricardo Acras