Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there something similar to JS 'Promise.all()' in Ruby?

Below is a code that should be optimized:

def statistics
  blogs = Blog.where(id: params[:ids])
  results = blogs.map do |blog|
    {
      id: blog.id,
      comment_count: blog.blog_comments.select("DISTINCT user_id").count
    }
  end
  render json: results.to_json
end

Each SQL query cost around 200ms. If I have 10 blog posts, this function would take 2s because it runs synchronously. I can use GROUP BY to optimize the query, but I put that aside first because the task could be a third party request, and I am interested in how Ruby deals with async.

In Javascript, when I want to dispatch multiple asynchronous works and wait all of them to resolve, I can use Promise.all(). I wonder what the alternatives are for Ruby language to solve this problem.

Do I need a thread for this case? And is it safe to do that in Ruby?

like image 639
chaintng Avatar asked Oct 16 '25 14:10

chaintng


1 Answers

There are multiple ways to solve this in ruby, including promises (enabled by gems).

JavaScript accomplishes asynchronous execution using an event loop and event driven I/O. There are event libraries to accomplish the same thing in ruby. One of the most popular is eventmachine.

As you mentioned, threads can also solve this problem. Thread-safety is a big topic and is further complicated by different thread models in different flavors of ruby (MRI, JRuby, etc). In summary I'll just say that of course threads can be used safely... there are just times when that is difficult. However, when used with blocking I/O (like to an API or a database request) threads can be very useful and fairly straight-forward. A solution with threads might look something like this:

# run blocking IO requests simultaneously
thread_pool = [
  Thread.new { execute_sql_1 },
  Thread.new { execute_sql_2 },
  Thread.new { execute_sql_3 },
  # ...
]

# wait for the slowest one to finish
thread_pool.each(&:join)

You also have access to other currency models, like the actor model, async classes, promises, and others enabled by gems like concurrent-ruby.

Finally, ruby concurrency can take the form of multiple processes communicating through built in mechanisms (drb, sockets, etc) or through distributed message brokers (redis, rabbitmq, etc).

like image 157
Carl Zulauf Avatar answered Oct 18 '25 05:10

Carl Zulauf



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!