i am current porting a ruby gem like Foreman but things are designed to run in both foreground/background into Crystal, I am quite ensure it is doable, although there are many challenges.
Following is one about IO.select
, i am not a expect of it, in fact, manipulate it directly rarely, I need help.
The original ruby version code is here, following is the copy.
def listen
loop do
# IO.select IOs, timeout 30 seconds
io = IO.select([@sp_reader] + @listeners.keys, nil, nil, 30)
if io && io.first
io.first.each do |io|
if io == @sp_reader
io.read_nonblock(999)
next
end
Thread.new(io) do |io|
handle_client(client: io.accept, server: io)
end
end
end
@stopped_processes.reject do |process|
if io = @listeners.key(process)
Procodile.log nil, "proxy", "Stopped proxy listener for #{process.name}"
io.close
@listeners.delete(io)
end
true
end
end
rescue e
Procodile.log nil, "proxy", "Exception: #{e.class}: #{e.message}"
Procodile.log nil, "proxy", e.backtrace[0, 5].join("\n")
end
Now, i want to port to Crystal, because the IO.select was removed, as describe by this,
But, i don’t sure how to handle this, following is a attempt.
def listen
sleep_chan = Channel(Nil).new
sp_reader_chan = Channel(Nil).new
listener_chan = Channel(Nil).new
spawn do
loop do
sleep 30
sleep_chan.send nil
end
end
spawn do
loop do
@sp_reader.read(Bytes.new(999))
sp_reader_chan.send nil
end
end
@listeners.keys.each do |io|
spawn do
loop do
handle_client(client: io.accept, server: io)
listener_chan.send nil
end
end
end
loop do
select
when sp_reader_chan.receive
when listener_chan.receive
when sleep_chan.receive
end
@stopped_processes.reject do |process|
if io = @listeners.key(process)
Procodile.log nil, "proxy", "Stopped proxy listener for #{process.name}"
io.close
@listeners.delete(io)
end
true
end
end
end
Please help point out the issue, incorrect usage.
Hopefully more and more Ruby code can be rewritten in Crystal.