DEV Community

Cover image for Make Ruby code thread-safe
Vladislav Kopylov
Vladislav Kopylov

Posted on

Make Ruby code thread-safe

For example, we have ruby-code that execs some I/O operations in a row (for instance, it runs 3 queries to database).

class A def initialize @data = {} end # Run class and collect data to the hash def call do_1 do_2 do_3 @data end private def do_1 @data['1'] = exec_some_io end def do_2 @data['2'] = exec_some_io end def do_3 @data['3'] = exec_some_io end def exec_some_io time = (0.1..0.2).step(0.01).to_a.sample sleep(time) [1,2,3].sample end end puts A.new.call 
Enter fullscreen mode Exit fullscreen mode

In order to optimise code and reduce execution time, we can rewrite it and use Thread.

class A def call [ Thread.new { do_1 }, Thread.new { do_2 }, Thread.new { do_3 }, ].map(&:join) @data end private def do_1 @data['1'] = exec_some_io end def do_2 @data['2'] = exec_some_io end def do_3 @data['3'] = exec_some_io end end 
Enter fullscreen mode Exit fullscreen mode

Please, don't write the code like that. Firstly, methods do_1, do_2, do_3 know a lot of information about the data structure. Secondly, as we are using threads, we don't control context. It's dangerous and can produce errors in our application. In order to fix it, we have to use value method. It's easy to rewrite:

class A def call @data = { '1' => Thread.new { do_1 }, '2' => Thread.new { do_2 }, '3' => Thread.new { do_3 }, }.transform_values(&:value) @data end private def do_1 exec_some_io end def do_2 exec_some_io end def do_3 exec_some_io end end 
Enter fullscreen mode Exit fullscreen mode

Now, our ruby-code is thread-safe.

Top comments (0)