Basic Concurrency in Ruby. Really Basic.
Tags: ruby, concurrency, mri, cruby
Published: 2018-02-17 17:43:16

---
title: "Basic Concurrency in Ruby. Really Basic."
description: "We read a lot about concurrency in Ruby. How do you actually do it, though? Here's how I made some concurrent, non-blocking API calls from a Rails app."
published: true
tags: Ruby, concurrency, MRI, CRuby
canonical_url: https://www.briankephart.com/basic-concurrency-in-ruby
---
As a new coder, I often find documentation less than helpful. Or at least, very difficult to parse. Recently I ran into this while reading the documentation for the concurrent-ruby gem. I want to be clear, the documentation for this gem is not bad. On the contrary, it is dense and thorough, which can nevertheless be detrimental for looking up a simple use case. I had trouble stripping it down to what I needed, so I'm presenting my results here as a reference for others.

CRuby is not known for being good at concurrency within a single process (such as a single web request). You can create new threads within a process, but those threads will execute one at a time due to a Global Interpreter Lock. That means that you can't really execute two instructions at once, but you can start multiple operations and Ruby will switch between them as resources allow. In practice, this is most often useful when making calls to external services with significant latency. You can start an i/o operation, then execute some code while waiting for the result.

The previous paragraph is what I knew from various internet readings. I didn't know how to actually do it in code, though. For a long time I didn't need to.

Our business uses third-party scheduling software, and I needed to make some API calls to this software for the app that I'm building. These API calls are slow (several seconds apiece), so I wanted to make them concurrently rather than sequentially. This is a textbook case for concurrency in CRuby, since the majority of time is spent waiting on i/o rather than code execution.

Here's what I wanted to do concurrently:
```ruby
var_1 = some_api_call_result
var_2 = some_other_api_call_result
# some code that uses var_1 and var_2
```

And here's how I did it in the end:
*[note: See the comments for how to do this without the concurrent-ruby gem, using the Ruby standard library!]*
```ruby
var_1 = Concurrent::Future.execute { some_api_call }
var_2 = Concurrent::Future.execute { some_other_api_call }
var_1 = var_1.value
var_2 = var_2.value
# some code that uses var_1 and var_2
```

The `execute` method tells the interpreter to run the API call and continue program execution while waiting for it to complete. The `value` method returns the result of the code block passed to the `execute` method, blocking program execution if necessary while the operation completes, ensuring that the values are present for executing the code that follows.

Using this pattern, i/o operations can be run asynchronously by creating `Concurrent::Future` ([docs](http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Future.html)) objects and passing the required code as a block to the `execute` method. There is no need to block program execution until the result of the i/o operation is needed by the program, at which point the `value` method is used to obtain it.

This seems to me like the most basic form of concurrency possible within a Ruby program, yet I had trouble finding it presented in a really simple way. I hope it helps someone else dealing with concurrency for the first time, and I encourage others to post their stories of basic operations that were difficult to learn.