redis / hiredis-rb

Ruby wrapper for hiredis
BSD 3-Clause "New" or "Revised" License
320 stars 90 forks source link

Add support for Ruby 3.0 Fiber Scheduler #77

Open machty opened 2 years ago

machty commented 2 years ago

This implements support for the Ruby 3.0+ Fiber Scheduler interface.

If a Fiber Scheduler (such as the one defined by the Async library) is present, then we invoke its hooks whenever we're about to perform an IO wait operation. This makes it possible for the scheduler to pass control to another Fiber/task while waiting for the socket to become readable/writable.

Closes #76

Example

Ruby 3.1 + Async 2.0.0:

# using two separate Redis clients REDIS1 and REDIS2 for simple test;
# typically we'd use a pool

Async do |t|
  t.async do
    puts "1: starting blpop loop\n"
    loop do
      value = REDIS1.blpop "test_queue"
      puts "received value #{value}\n"
    end
  end

  t.async do
    puts "2: starting enqueuer loop\n"
    i = 0
    loop do
      sleep 1
      REDIS2.rpush "test_queue", i
      i += 1
    end
  end
end

This outputs:

1: starting blpop loop
2: starting enqueuer loop
received value ["test_queue", "0"]
received value ["test_queue", "1"]
received value ["test_queue", "2"]
received value ["test_queue", "3"]
received value ["test_queue", "4"]
received value ["test_queue", "5"]
...

Without this PR, the output is just the following (it just hangs):

# 1: starting blpop loop

TODO:

machty commented 2 years ago

cc @ioquatix

This is the first time I've done work on a C extension, not to mention working with the native Fiber scheduler API, so I welcome any feedback. I've already added a few comments; curious as to your thoughts on whether some of the io_from_fd copypasta can be removed.

ioquatix commented 2 years ago

I see so we are missing an interface to wrap a native FD into a Ruby IO at the extension level?