README.md in timeout-extensions-0.1.0 vs README.md in timeout-extensions-0.1.1
- old
+ new
@@ -30,50 +30,148 @@
The Timeout::Extensions gem enhances the Ruby standard library's
`timeout.rb` API:
```ruby
-require 'timeout/extensions'
+require 'timeout'
-Timeout.new(30) do
+Timeout.timeout(30) do
# Times out after 30 seconds raising Timeout::Error
end
```
However, where `timeout.rb` provides one implementation, the Timeout Gem
provides support for multiple, swappable backends:
```ruby
-require 'timeout/extensions'
+# examples/even_odd.rb
+require "timeout/extensions"
-module MyTimeoutThingy
- # WARNING: don't use this. It's just a strawman example
- def self.timeout(secs)
- current = Thread.current
- sleeper = Thread.start do
- begin
- sleep secs
- rescue => ex
- current.raise ex
- else
- current.raise Timeout::Error, "execution expired"
- end
+module MyAwesomeJob
+ def self.perform
+ timeout(5) do
+ sleep 5 # perform incredibly heavy job
end
- return yield(secs)
- ensure
- if sleeper
- sleeper.kill
- sleeper.join
- end
+ rescue => e
+ puts "job failed: #{e.message}"
end
end
+module MyOwnTimeout
+ CustomTimeoutError = Class.new(RuntimeError)
+ def self.call(sec, *)
+ puts "pretending to wait for #{sec} seconds..."
+ yield
+ end
+end
+
+
+5.times.map do |i|
+ Thread.start do
+ Thread.current.timeout_handler = MyOwnTimeout
+ MyAwesomeJob.perform
+ end
+end.join(&:join)
+__END__
+
+pretending to wait for 2 seconds...
+pretending to wait for 2 seconds...
+job failed: execution expired
+job failed: execution expired
+job failed: execution expired
+
+```
+
+You can also setup a timeout backend temporarily, for the duration of a block:
+
+```ruby
Timeout.backend(MyTimeoutThingy) do
- Timeout.new(30) do
+ Timeout.timeout(30) do
# Manage timeouts with MyTimeoutThingy instead of timeout.rb
+ # MyTimeoutThingy just responds to #call(sec, ex)
# Plug in your own backend just this easily!
end
end
+```
+
+This library also supports setting your own sleep implementation:
+
+```ruby
+
+Thread.start do
+ Thread.current.sleep_handler = YourSleepHandler # must also respond to #call(Integer or nil)
+....
+```
+
+
+## Celluloid Support
+
+This gem provides celluloid support out of the box.
+
+Celluloid has its own actor timeout and sleep methods, which are implemented using the ```timer``` gem and do not block its mailbox. These have to be called inside your celluloid actor context however, thereby limiting the scope of your code:
+
+```ruby
+# examples/celluloid.rb
+require "celluloid"
+
+module MyJob
+ def self.perform
+ puts "performing"
+ sleep 5
+ puts "performed!"
+ end
+end
+
+class Worker
+ include Celluloid
+
+ def develop
+ MyJob.perform
+ end
+
+ def ten_times_developer
+ 10.times.each { async(:develop) }
+ end
+end
+
+Worker.new.async(:ten_times_developer)
+
+sleep
+__END__
+performing
+performed!
+performing
+performed!
+performing
+performed!
+performing
+performed!
+performing
+performed!
+...
+```
+
+But if your had the extension in the first line:
+```
+require 'timeout/extensions/celluloid'
+....
+__END__
+performing
+performing
+performing
+performing
+performing
+performing
+performing
+performing
+performing
+performing
+performed!
+performed!
+performed!
+performed!
+performed!
+....
```
## Supported Ruby Versions
This library aims to support and is [tested against][travis] the following Ruby