Libuv is a cross platform asynchronous IO implementation that powers NodeJS. It supports sockets, both UDP and TCP, filesystem watch, TTY, Pipes and other asynchronous primitives like timer, check, prepare and idle.
The Libuv gem contains Libuv and a Ruby wrapper that implements pipelined promises for asynchronous flow control and coroutines / futures for untangling evented code
Libuv supports multiple reactors that can run on different threads.
For convenience the thread local or default reactor can be accessed via the reactor method
You can pass a block to be executed on the reactor and the reactor will run until there is nothing left to do.
require 'libuv'
reactor do |reactor|
reactor.timer {
puts "5 seconds passed"
}.start(5000)
end
puts "reactor stopped. No more IO to process"
Promises are used to simplify code flow.
require 'libuv'
reactor do |reactor|
reactor.tcp { |data, socket|
puts "received: #{data}"
socket.close
}
.connect('127.0.0.1', 3000) { |socket|
socket.start_read
.write("GET / HTTP/1.1\r\n\r\n")
}
.catch { |error|
puts "error: #{error}"
}
.finally {
puts "socket closed"
}
end
Continuations are used if callbacks are not defined
require 'libuv'
reactor do |reactor|
begin
reactor.tcp { |data, socket|
puts "received: #{data}"
socket.close
}
.connect('127.0.0.1', 3000)
.start_read
.write("GET / HTTP/1.1\r\n\r\n")
rescue => error
puts "error: #{error}"
end
end
Any promise can be converted into a continuation
require 'libuv'
reactor do |reactor|
# Perform work on the thread pool with promises
reactor.work {
10 * 2
}.then { |result|
puts "result using a promise #{result}"
}
# Use the coroutine helper to obtain the result without a callback
result = reactor.work {
10 * 3
}.value
puts "no additional callbacks here #{result}"
end
Check out the yard documentation
gem install libuv
or
git clone https://github.com/cotag/libuv.git
cd libuv
bundle install
rake compile
USE_GLOBAL_LIBUV will prevent compiling the packaged version.
libuv.(so | dylib | dll) on the PATH alreadyOn Windows the GEM ships with a pre-compiled binary. If you would like to build yourself:
set GYP_MSVS_VERSION=2017set LIBRARY_PATH=X:\win-builds-64\lib;X:\win-builds-64\x86_64-w64-mingw32\librake compileYou can host a TLS enabled server with multiple hostnames using SNI.
server = reactor.tcp
server.bind('0.0.0.0', 3000, **{
hosts: [{
private_key: '/blah.key',
cert_chain: '/blah.crt',
host_name: 'somehost.com',
},
{
private_key: '/blah2.key',
cert_chain: '/blah2.crt',
host_name: 'somehost2.com'
},
{
private_key: '/blah3.key',
cert_chain: '/blah3.crt',
host_name: 'somehost3.com'
}]
}) do |client|
client.start_tls
client.start_read
end
# at some point later
server.add_host(private_key: '/blah4.key', cert_chain: '/blah4.crt', host_name: 'somehost4.com')
server.remove_host('somehost2.com')
You don't have to specify any hosts at binding time.
Ruby
99.9%
Libuv is a cross platform asynchronous IO implementation that powers NodeJS. It supports sockets, both UDP and TCP, filesystem watch, TTY, Pipes and other asynchronous primitives like timer, check, prepare and idle.
The Libuv gem contains Libuv and a Ruby wrapper that implements pipelined promises for asynchronous flow control and coroutines / futures for untangling evented code
Libuv supports multiple reactors that can run on different threads.
For convenience the thread local or default reactor can be accessed via the reactor method
You can pass a block to be executed on the reactor and the reactor will run until there is nothing left to do.
require 'libuv'
reactor do |reactor|
reactor.timer {
puts "5 seconds passed"
}.start(5000)
end
puts "reactor stopped. No more IO to process"
Promises are used to simplify code flow.
require 'libuv'
reactor do |reactor|
reactor.tcp { |data, socket|
puts "received: #{data}"
socket.close
}
.connect('127.0.0.1', 3000) { |socket|
socket.start_read
.write("GET / HTTP/1.1\r\n\r\n")
}
.catch { |error|
puts "error: #{error}"
}
.finally {
puts "socket closed"
}
end
Continuations are used if callbacks are not defined
require 'libuv'
reactor do |reactor|
begin
reactor.tcp { |data, socket|
puts "received: #{data}"
socket.close
}
.connect('127.0.0.1', 3000)
.start_read
.write("GET / HTTP/1.1\r\n\r\n")
rescue => error
puts "error: #{error}"
end
end
Any promise can be converted into a continuation
require 'libuv'
reactor do |reactor|
# Perform work on the thread pool with promises
reactor.work {
10 * 2
}.then { |result|
puts "result using a promise #{result}"
}
# Use the coroutine helper to obtain the result without a callback
result = reactor.work {
10 * 3
}.value
puts "no additional callbacks here #{result}"
end
Check out the yard documentation
gem install libuv
or
git clone https://github.com/cotag/libuv.git
cd libuv
bundle install
rake compile
USE_GLOBAL_LIBUV will prevent compiling the packaged version.
libuv.(so | dylib | dll) on the PATH alreadyOn Windows the GEM ships with a pre-compiled binary. If you would like to build yourself:
set GYP_MSVS_VERSION=2017set LIBRARY_PATH=X:\win-builds-64\lib;X:\win-builds-64\x86_64-w64-mingw32\librake compileYou can host a TLS enabled server with multiple hostnames using SNI.
server = reactor.tcp
server.bind('0.0.0.0', 3000, **{
hosts: [{
private_key: '/blah.key',
cert_chain: '/blah.crt',
host_name: 'somehost.com',
},
{
private_key: '/blah2.key',
cert_chain: '/blah2.crt',
host_name: 'somehost2.com'
},
{
private_key: '/blah3.key',
cert_chain: '/blah3.crt',
host_name: 'somehost3.com'
}]
}) do |client|
client.start_tls
client.start_read
end
# at some point later
server.add_host(private_key: '/blah4.key', cert_chain: '/blah4.crt', host_name: 'somehost4.com')
server.remove_host('somehost2.com')
You don't have to specify any hosts at binding time.
Ruby
99.9%