Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

What's the correct way of doing recurrent timers? #27

Closed
dblock opened this issue Sep 12, 2018 · 1 comment
Closed

What's the correct way of doing recurrent timers? #27

dblock opened this issue Sep 12, 2018 · 1 comment
Labels

Comments

@dblock
Copy link

dblock commented Sep 12, 2018

I am looking for the equivalent of every in Celluloid. It was suggested to loop and task.sleep, however it doesn't behave the same way.

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "1: #{i}"
      task.sleep 3
    end
  end

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "2: #{i}"
      task.sleep 3
    end
  end
1: 0
1: 1
1: 2
2: 0
2: 1
2: 2

that said, it works if both reactor runs are inside of a reactor

::Async::Reactor.run do
  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "1: #{i}"
      task.sleep 3
    end
  end

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "2: #{i}"
      task.sleep 3
    end
  end
end
1: 0
2: 0
1: 1
2: 1
1: 2
2: 2

Is the latter the correct way?

Maybe implementing a higher level timers API could be valuable? It would ensure to start a "parent" reactor, always behave like the second version, and have predictable (eg. not bail out on error) error behavior?

I also see

def_delegators :@timers, :every, :after
.

require 'async'

i = 0
j = 0

reactor = Async::Reactor.new

reactor.run do |task|
  reactor.every 3 do
    puts "1: #{i}"
    i += 1
  end

  reactor.every 3 do
    puts "2: #{j}"
    j += 1
  end
end

Works as expected. Does nothing without reactor.run. Maybe it just needs documentation and/or being wrapped and error out if not running under a reactor?

@ioquatix
Copy link
Member

If you run it like this:

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "1: #{i}"
      task.sleep 3
    end
  end

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "2: #{i}"
      task.sleep 3
    end
  end

You are running two sequential reactors and there is no interaction between the two.

::Async::Reactor.run do
  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "1: #{i}"
      task.sleep 3
    end
  end

  ::Async::Reactor.run do |task|
    3.times do |i|
      puts "2: #{i}"
      task.sleep 3
    end
  end
end

is the correct way.

reactor.run do |task|
  reactor.every 3 do
    puts "1: #{i}"
    i += 1
  end

  reactor.every 3 do
    puts "2: #{j}"
    j += 1
  end
end

This way is risky because it doesn't run in a task context. You should probably avoid it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants