timeout-extensions 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ac5f8d21d026acd98f1d9dd234e7a580a8efa2bc
4
- data.tar.gz: fa3e5860cf5f98d836d8e3cb1350913453163dbf
3
+ metadata.gz: 813e3de49e1c2704e6157e53a823679be242c431
4
+ data.tar.gz: f729d9543b3b4ffef625bd2e637a10310749dd91
5
5
  SHA512:
6
- metadata.gz: 326430abdffa6d8a8c21dc101a802cb193545fc1648b2c345c392aca3d899a1b648cf49f0d9e2885387358d8d6667cbd62c95fb012faab8365d5b84f0f20c878
7
- data.tar.gz: 50a5b3f7b721d8f181dd533ecf53d2c2b0c4fcb417b8530af6b5fe060e9c5b4de7c5ec90e5d0737e27fb233385440716b6fb6f17e1aca4e9634a3a68ddaf957c
6
+ metadata.gz: ed58d38698b921144f4553212ff8e1172c65caa9851430df9d07c5fbdfb99b0f25d6182ec7afaba6414ab64f5333e841eda108f95f7f57221d99547720b7d98f
7
+ data.tar.gz: 38928ed605acb6deb62a6fa3e9d2e341312b0ae963418395626a147cad9d998649679d4d2df1164c746b4fcd3b98a1ab042dce3d282749958bb421ad9ea85287
data/CHANGES.md CHANGED
@@ -1,3 +1,7 @@
1
+ ## 0.1.1 (2016-07-08)
2
+
3
+ * Use a module to patch ::Thread
4
+
1
5
  ## 0.1.0 (2016-07-02)
2
6
 
3
7
  * Initial release.
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source "https://rubygems.org"
2
2
 
3
3
  gemspec
4
4
 
5
+ gem "celluloid"
6
+
5
7
  group :development, :test do
6
8
  gem "rake"
7
9
  end
data/README.md CHANGED
@@ -32,9 +32,9 @@ The Timeout::Extensions gem enhances the Ruby standard library's
32
32
  `timeout.rb` API:
33
33
 
34
34
  ```ruby
35
- require 'timeout/extensions'
35
+ require 'timeout'
36
36
 
37
- Timeout.new(30) do
37
+ Timeout.timeout(30) do
38
38
  # Times out after 30 seconds raising Timeout::Error
39
39
  end
40
40
  ```
@@ -43,38 +43,136 @@ However, where `timeout.rb` provides one implementation, the Timeout Gem
43
43
  provides support for multiple, swappable backends:
44
44
 
45
45
  ```ruby
46
- require 'timeout/extensions'
47
-
48
- module MyTimeoutThingy
49
- # WARNING: don't use this. It's just a strawman example
50
- def self.timeout(secs)
51
- current = Thread.current
52
- sleeper = Thread.start do
53
- begin
54
- sleep secs
55
- rescue => ex
56
- current.raise ex
57
- else
58
- current.raise Timeout::Error, "execution expired"
59
- end
60
- end
61
- return yield(secs)
62
- ensure
63
- if sleeper
64
- sleeper.kill
65
- sleeper.join
46
+ # examples/even_odd.rb
47
+ require "timeout/extensions"
48
+
49
+ module MyAwesomeJob
50
+ def self.perform
51
+ timeout(5) do
52
+ sleep 5 # perform incredibly heavy job
66
53
  end
54
+ rescue => e
55
+ puts "job failed: #{e.message}"
56
+ end
57
+ end
58
+
59
+ module MyOwnTimeout
60
+ CustomTimeoutError = Class.new(RuntimeError)
61
+ def self.call(sec, *)
62
+ puts "pretending to wait for #{sec} seconds..."
63
+ yield
67
64
  end
68
65
  end
69
66
 
67
+
68
+ 5.times.map do |i|
69
+ Thread.start do
70
+ Thread.current.timeout_handler = MyOwnTimeout
71
+ MyAwesomeJob.perform
72
+ end
73
+ end.join(&:join)
74
+ __END__
75
+
76
+ pretending to wait for 2 seconds...
77
+ pretending to wait for 2 seconds...
78
+ job failed: execution expired
79
+ job failed: execution expired
80
+ job failed: execution expired
81
+
82
+ ```
83
+
84
+ You can also setup a timeout backend temporarily, for the duration of a block:
85
+
86
+ ```ruby
70
87
  Timeout.backend(MyTimeoutThingy) do
71
- Timeout.new(30) do
88
+ Timeout.timeout(30) do
72
89
  # Manage timeouts with MyTimeoutThingy instead of timeout.rb
90
+ # MyTimeoutThingy just responds to #call(sec, ex)
73
91
  # Plug in your own backend just this easily!
74
92
  end
75
93
  end
76
94
  ```
77
95
 
96
+ This library also supports setting your own sleep implementation:
97
+
98
+ ```ruby
99
+
100
+ Thread.start do
101
+ Thread.current.sleep_handler = YourSleepHandler # must also respond to #call(Integer or nil)
102
+ ....
103
+ ```
104
+
105
+
106
+ ## Celluloid Support
107
+
108
+ This gem provides celluloid support out of the box.
109
+
110
+ 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:
111
+
112
+ ```ruby
113
+ # examples/celluloid.rb
114
+ require "celluloid"
115
+
116
+ module MyJob
117
+ def self.perform
118
+ puts "performing"
119
+ sleep 5
120
+ puts "performed!"
121
+ end
122
+ end
123
+
124
+ class Worker
125
+ include Celluloid
126
+
127
+ def develop
128
+ MyJob.perform
129
+ end
130
+
131
+ def ten_times_developer
132
+ 10.times.each { async(:develop) }
133
+ end
134
+ end
135
+
136
+ Worker.new.async(:ten_times_developer)
137
+
138
+ sleep
139
+ __END__
140
+ performing
141
+ performed!
142
+ performing
143
+ performed!
144
+ performing
145
+ performed!
146
+ performing
147
+ performed!
148
+ performing
149
+ performed!
150
+ ...
151
+ ```
152
+
153
+ But if your had the extension in the first line:
154
+ ```
155
+ require 'timeout/extensions/celluloid'
156
+ ....
157
+ __END__
158
+ performing
159
+ performing
160
+ performing
161
+ performing
162
+ performing
163
+ performing
164
+ performing
165
+ performing
166
+ performing
167
+ performing
168
+ performed!
169
+ performed!
170
+ performed!
171
+ performed!
172
+ performed!
173
+ ....
174
+ ```
175
+
78
176
  ## Supported Ruby Versions
79
177
 
80
178
  This library aims to support and is [tested against][travis] the following Ruby
@@ -0,0 +1,25 @@
1
+ require "timeout/extensions/celluloid"
2
+
3
+ module MyJob
4
+ def self.perform
5
+ puts "performing"
6
+ sleep 5
7
+ puts "performed!"
8
+ end
9
+ end
10
+
11
+ class Worker
12
+ include Celluloid
13
+
14
+ def develop
15
+ MyJob.perform
16
+ end
17
+
18
+ def ten_times_developer
19
+ 10.times.each { async(:develop) }
20
+ end
21
+ end
22
+
23
+ Worker.new.async(:ten_times_developer)
24
+
25
+ sleep
@@ -0,0 +1,26 @@
1
+ require "timeout/extensions"
2
+
3
+ module MyAwesomeJob
4
+ def self.perform
5
+ timeout(2) do
6
+ sleep 3 # perform incredibly heavy job
7
+ end
8
+ rescue => e
9
+ puts "job failed: #{e.message}"
10
+ end
11
+ end
12
+
13
+ module MyOwnTimeout
14
+ CustomTimeoutError = Class.new(RuntimeError)
15
+ def self.call(sec, *)
16
+ puts "pretending to wait for #{sec} seconds..."
17
+ yield
18
+ end
19
+ end
20
+
21
+ Array(5.times).map do |i|
22
+ Thread.start do
23
+ Thread.current.timeout_handler = MyOwnTimeout if i.odd?
24
+ MyAwesomeJob.perform
25
+ end
26
+ end.map(&:join)
@@ -1,4 +1,5 @@
1
1
  require "timeout/extensions/version"
2
+ require "timeout"
2
3
 
3
4
  # Core extensions to Thread
4
5
  #
@@ -48,3 +49,15 @@ module Timeout::Extensions
48
49
  #
49
50
  ::Object.prepend KernelMethods
50
51
  end
52
+
53
+ module Timeout
54
+ def self.backend(handler)
55
+ default_handler = Thread.current.timeout_handler
56
+ begin
57
+ Thread.current.timeout_handler = handler
58
+ yield
59
+ ensure
60
+ Thread.current.timeout_handler = default_handler
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,52 @@
1
+ require "timeout/extensions"
2
+ require "celluloid"
3
+ module Celluloid
4
+ module TimeoutExtensions
5
+ def timeout_handler
6
+ @timeout_handler ||= Celluloid.method(:timeout)
7
+ end
8
+
9
+ def sleep_handler
10
+ @sleep_handler ||= Celluloid.method(:sleep)
11
+ end
12
+ end
13
+
14
+ # Reopening the thread class to define the time handlers and pointing them to celluloid respective methodsx
15
+ class Thread
16
+ include TimeoutExtensions
17
+ end
18
+
19
+ ####################
20
+ #
21
+ # Celluloid Monkey-Patch Alert!!!!
22
+ # I would really like to remove this but, but I first need this pull request accepted:
23
+ # https://github.com/celluloid/celluloid/pull/491
24
+ #
25
+ # These methods have kept the same functionality for quite some time, therefore are quite stable,
26
+ # I just moved the locations and updated/corrected the method signatures.
27
+ #
28
+ ###################
29
+
30
+ def self.timeout(duration, klass = nil)
31
+ bt = caller
32
+ task = Task.current
33
+ klass ||= TaskTimeout
34
+ timers = Thread.current[:celluloid_actor].timers
35
+ timer = timers.after(duration) do
36
+ exception = klass.new("execution expired")
37
+ exception.set_backtrace bt
38
+ task.resume exception
39
+ end
40
+ yield
41
+ ensure
42
+ timer.cancel if timer
43
+ end
44
+
45
+ class Actor
46
+ # Using the module method now instead of doing everything by itself.
47
+ def timeout(*args)
48
+ Celluloid.timeout(*args) { yield }
49
+ end
50
+ private :timeout
51
+ end
52
+ end
@@ -1,3 +1,3 @@
1
1
  module Timeout::Extensions
2
- VERSION = "0.1.0".freeze
2
+ VERSION = "0.1.1".freeze
3
3
  end
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe Timeout do
4
+ describe ".backend" do
5
+ let(:handler) { double(:handler) }
6
+ it "allows to switch timeout backends on the fly" do
7
+ expect(Thread.current.timeout_handler).to be_nil
8
+ Timeout.backend(handler) do
9
+ expect(Thread.current.timeout_handler).to be(handler)
10
+ expect(handler).to receive(:call).with(2)
11
+ Timeout.timeout(2) {}
12
+ end
13
+ expect(Thread.current.timeout_handler).to be_nil
14
+ end
15
+ end
16
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: timeout-extensions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-07-03 00:00:00.000000000 Z
12
+ date: 2016-07-08 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: A timeout extension for Ruby which plugs into multiple timeout backends
15
15
  email:
@@ -27,11 +27,15 @@ files:
27
27
  - LICENSE.txt
28
28
  - README.md
29
29
  - Rakefile
30
+ - examples/celluloid.rb
31
+ - examples/even_odd.rb
30
32
  - lib/timeout/extensions.rb
33
+ - lib/timeout/extensions/celluloid.rb
31
34
  - lib/timeout/extensions/version.rb
32
35
  - log/.gitkeep
33
36
  - spec/spec_helper.rb
34
37
  - spec/timeout/extensions_spec.rb
38
+ - spec/timeout_spec.rb
35
39
  - timeout-extensions.gemspec
36
40
  homepage: https://github.com/celluloid/timeout-extensions
37
41
  licenses:
@@ -60,3 +64,4 @@ summary: Extensions to the Ruby standard library's timeout API
60
64
  test_files:
61
65
  - spec/spec_helper.rb
62
66
  - spec/timeout/extensions_spec.rb
67
+ - spec/timeout_spec.rb