eventkit 0.0.4 → 1.0

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: 6cf7b1a61743aa9b00613324e6279acce0df9d7b
4
- data.tar.gz: c6627672c75ddd5007bc414f8f37a2f9d2565a4d
3
+ metadata.gz: 3535ba4fd3f864f13fc1a39c45eb37a560cb0aed
4
+ data.tar.gz: 5653234f81a48b182d3e6b60f3eb225cf758275b
5
5
  SHA512:
6
- metadata.gz: 6baac81b5c1c47cc2b38a759b7da5460eab177c6d1d480dca132fab014013351f4ac6273c6d1fe3abed16cd670da6f284a402b69282b0a3fdff82a95ef08e84b
7
- data.tar.gz: 15f3fdff27e494d72b37aaa40004c47bcdeef47957833b99c845d6102289b3570a65710262c23210d1f3f95c141d446ffb7153d3a2f6172c338ca87f714cc2ba
6
+ metadata.gz: e7129a03c555c04811b0aa19f4ce468130f02b57a531ea412c3d45a44e03333f4064d00c774ab2f24d04134d002bafdc388abdd4047daa527d15b4e6e721d4a3
7
+ data.tar.gz: f96f126b88c526f4318b77d0fb76b9250374f021eb20a66336f24f9de68df153f235469bac8c39d08e57edc57dfb2d71c8fea403f28970d5cd35038fefe0a906
data/README.md CHANGED
@@ -3,174 +3,21 @@
3
3
  [![Build Status](https://travis-ci.org/omartell/eventkit.svg?branch=master)](https://travis-ci.org/omartell/eventkit)
4
4
 
5
5
  A basic toolkit for asynchronous event driven applications. The
6
- current version includes an Event Loop to perform non blocking IO and
6
+ toolkit includes an Event Loop to perform non blocking IO and
7
7
  a promises A+ implementation to coordinate asychronous tasks.
8
8
 
9
+ This gem bundles up the [eventkit-eventloop](http://github.com/omartell/eventkit-eventloop) and [eventkit-promise](http://github.com/omartell/eventkit-promise) gems.
10
+
9
11
  ## Installation
10
12
 
11
13
  Add this line to your application's Gemfile:
12
14
 
13
15
  ```ruby
14
- gem 'eventkit'
15
- ```
16
-
17
- ## Event Loop Usage
18
-
19
- Eventkit provides a basic Event Loop on top of Ruby's IO.select to perform non blocking IO.
20
- Callbacks can be registered to monitor the readability or writability of IO objects.
21
- These callbacks are executed when the IO object is ready to be read or written to.
22
-
23
- Another feature is timers, which allows you to execute code at some point in the future.
24
-
25
- ```ruby
26
- require 'eventkit'
27
-
28
- # Getting notified when an IO object is ready to be read or written
29
- event_loop = Eventkit::EventLoop.new
30
-
31
- server = TCPServer.new('localhost', 9595)
32
-
33
- client = TCPSocket.new('localhost', 9595)
34
-
35
- event_loop.register_read(server) do |server|
36
- # This will be executed every time a new connection is ready to be accepted
37
- connection, _ = server.accept_nonblock
38
- event_loop.register_write(connection) do |connection|
39
- bytes_written = connection.write_nonblock('hello world')
40
- end
41
- end
42
-
43
- event_loop.start
44
-
45
-
46
- # Unsubscribing from notifications
47
- # A single read
48
- event_loop.deregister_read(io_object, handler)
49
-
50
- # A single write
51
- event_loop.deregister_write(io_object, handler)
52
-
53
- # All handlers
54
- event_loop.deregister_write(io_object)
55
- event_loop.deregister_read(io_object)
56
-
57
-
58
- # Registering a handler to be run on the next tick
59
- event_loop = Eventkit::EventLoop.new
60
-
61
- event_loop.on_next_tick do
62
- puts 'hello world'
63
- event_loop.stop
64
- end
65
-
66
- event_loop.start
67
-
68
-
69
- # Registering timers
70
-
71
- event_loop = Eventkit::EventLoop.new
72
-
73
- event_loop.register_timer(run_in: 5) do
74
- # Block executes after 5 seconds have passed
75
- puts 'hello world'
76
- event_loop.stop
77
- end
78
-
79
- event_loop.start
80
- ```
81
-
82
- ## Promises Usage
83
-
84
- Eventkit also provides an implementation of the [Promise A+ specification](https://promisesaplus.com/),
85
- which allows you coordinate different asynchronous tasks while still programming with values.
86
-
87
- If you're only interested in promises, then eventkit-promise is also available as a [separate gem] (https://rubygems.org/gems/eventkit-promise).
88
-
89
- ```ruby
90
- require 'eventkit/promise'
91
-
92
- # Resolving a promise
93
-
94
- promise = Eventkit::Promise.new
95
-
96
- promise.then(->(value) { value + 1 })
97
-
98
- promise.resolve(1)
99
-
100
- promise.value # => 1
101
-
102
- # Rejecting a promise
103
-
104
- promise = Eventkit::Promise.new
105
-
106
- promise.then(
107
- ->(value) {
108
- value + 1
109
- },
110
- ->(error) {
111
- log(error.message)
112
- }
113
- )
114
-
115
- promise.reject(NoMethodError.new('Undefined method #call'))
116
-
117
- promise.reason # => <NoMethodError: undefined method #call>
118
-
119
- # Chaining promises
120
-
121
- promise_a = Eventkit::Promise.new
122
-
123
- promise_b = promise_a
124
- .then(->(v) { v + 1 })
125
- .then(->(v) { v + 1 })
126
- .then(->(v) { v + 1 })
127
-
128
- promise_b.catch { |error|
129
- # Handle errors raised by any of the previous handlers
130
- }
131
-
132
- promise_a.resolve(1)
133
-
134
- promise_a.value # => 1
135
- promise_b.value # => 4
136
-
137
- # Resolving and fullfiling with another promise
138
-
139
- promise_a = Eventkit::Promise.new
140
- promise_b = Eventkit::Promise.new
141
-
142
- promise_a.resolve(promise_b)
143
-
144
- promise_b.resolve('foobar')
145
-
146
- promise_a.value # => foobar
147
-
148
- # Resolving and rejecting with another promise
149
-
150
- promise_a = Eventkit::Promise.new
151
- promise_b = Eventkit::Promise.new
152
-
153
- promise_a.resolve(promise_b)
154
-
155
- promise_b.reject('Ooops can not continue')
156
-
157
- promise_a.reason # => 'Ooops can not continue'
158
-
159
- # Initializing with a block
160
-
161
- promise = Promise.new do |p|
162
- p.resolve('foobar')
163
- end
164
-
165
- promise.value # => 'foobar'
166
-
16
+ gem 'eventkit', '~> 1.0'
167
17
  ```
168
18
 
169
- ## Contributing
19
+ ## Usage
170
20
 
171
- 1. Fork it ( https://github.com/[my-github-username]/eventkit/fork )
172
- 2. Create your feature branch (`git checkout -b my-new-feature`)
173
- 3. Commit your changes (`git commit -am 'Add some feature'`)
174
- 4. Push to the branch (`git push origin my-new-feature`)
175
- 5. Create a new Pull Request
176
- 6. Happy Hacking!
21
+ Check the documentation of
22
+ [eventkit-eventloop](http://github.com/omartell/eventkit-eventloop)
23
+ and [eventkit-promise](http://github.com/omartell/eventkit-promise).
@@ -1,11 +1,10 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'eventkit/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
6
  spec.name = 'eventkit'
8
- spec.version = Eventkit::VERSION
7
+ spec.version = '1.0'
9
8
  spec.authors = ['Oliver Martell']
10
9
  spec.email = ['oliver.martell@gmail.com']
11
10
  spec.summary = 'Experimental toolkit for asynchronous event driven applications'
@@ -23,5 +22,7 @@ Gem::Specification.new do |spec|
23
22
  spec.add_development_dependency 'pry', '~> 0.10.1'
24
23
  spec.add_development_dependency 'pry-doc', '~> 0.6.0'
25
24
  spec.add_development_dependency 'method_source', '~> 0.8.2'
26
- spec.add_runtime_dependency 'eventkit-promise', '~> 0.1.0'
25
+
26
+ spec.add_runtime_dependency 'eventkit-promise', '~> 1.0'
27
+ spec.add_runtime_dependency 'eventkit-eventloop', '~> 0.1.0'
27
28
  end
@@ -1,7 +1,2 @@
1
- require 'eventkit/version'
2
1
  require 'eventkit/event_loop'
3
2
  require 'eventkit/promise'
4
-
5
- module Eventkit
6
- # Your code goes here...
7
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventkit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: '1.0'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Oliver Martell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-21 00:00:00.000000000 Z
11
+ date: 2015-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -82,6 +82,20 @@ dependencies:
82
82
  version: 0.8.2
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: eventkit-promise
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: eventkit-eventloop
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
101
  - - "~>"
@@ -111,12 +125,7 @@ files:
111
125
  - Rakefile
112
126
  - eventkit.gemspec
113
127
  - lib/eventkit.rb
114
- - lib/eventkit/event_loop.rb
115
- - lib/eventkit/timer.rb
116
- - lib/eventkit/version.rb
117
- - spec/eventkit/event_loop_spec.rb
118
128
  - spec/spec_helper.rb
119
- - spec/support/async_helper.rb
120
129
  homepage: http://github.com/omartell/eventkit
121
130
  licenses:
122
131
  - MIT
@@ -142,7 +151,5 @@ signing_key:
142
151
  specification_version: 4
143
152
  summary: Experimental toolkit for asynchronous event driven applications
144
153
  test_files:
145
- - spec/eventkit/event_loop_spec.rb
146
154
  - spec/spec_helper.rb
147
- - spec/support/async_helper.rb
148
155
  has_rdoc:
@@ -1,95 +0,0 @@
1
- require 'set'
2
- require 'eventkit/timer'
3
-
4
- module Eventkit
5
- class EventLoopAlreadyStartedError < StandardError; end
6
-
7
- class EventLoop
8
- attr_reader :select_interval
9
- private :select_interval
10
-
11
- def initialize(config = {})
12
- @read_handlers = Hash.new { |h, k| h[k] = [] }
13
- @write_handlers = Hash.new { |h, k| h[k] = [] }
14
- @select_interval = config.fetch(:select_interval, 1 / 100_000)
15
- @timers = SortedSet.new
16
- @stopped = false
17
- @started = false
18
- end
19
-
20
- def start(&_block)
21
- if @started
22
- fail EventLoopAlreadyStartedError, 'This event loop instance has already started running'
23
- else
24
- @started = true
25
- end
26
-
27
- loop do
28
- if stop_scheduled?
29
- @stopped = false
30
- break
31
- end
32
- tick
33
- end
34
- end
35
-
36
- def stop
37
- @stopped = true
38
- @started = false
39
- end
40
-
41
- def stop_scheduled?
42
- @stopped
43
- end
44
-
45
- def tick
46
- ready_read, ready_write, _ = IO.select(@read_handlers.keys, @write_handlers.keys, [], select_interval)
47
- ready_read.each { |io|
48
- @read_handlers.fetch(io).each { |handler| handler.call(io) }
49
- } if ready_read
50
-
51
- ready_write.each { |io|
52
- @write_handlers.fetch(io).each { |handler| handler.call(io) }
53
- } if ready_write
54
-
55
- @timers.select(&:expired?).each { |timer|
56
- timer.handler.call
57
- @timers.delete(timer)
58
- }
59
- nil
60
- end
61
-
62
- def on_next_tick(&handler)
63
- register_timer(run_in: 0, &handler)
64
- end
65
-
66
- def register_timer(options, &handler)
67
- @timers << Timer.new(options.fetch(:run_in), handler)
68
- end
69
-
70
- def register_read(io, &listener)
71
- @read_handlers[io] += [listener]
72
- end
73
-
74
- def deregister_read(io, listener = nil)
75
- if listener
76
- @read_handlers[io] -= [listener]
77
- else
78
- @read_handlers[io] = []
79
- end
80
- end
81
-
82
- def register_write(io, &listener)
83
- @write_handlers[io] += [listener]
84
- end
85
-
86
- def deregister_write(io, listener = nil)
87
- if listener
88
- @write_handlers[io] -= [listener]
89
- else
90
- @write_handlers[io] = []
91
- end
92
- end
93
- end
94
- end
95
-
@@ -1,15 +0,0 @@
1
- module Eventkit
2
- Timer = Struct.new(:expires_in, :handler) do
3
- def initialize(seconds, handler)
4
- super(Time.now.to_f + seconds, handler)
5
- end
6
-
7
- def <=>(other)
8
- expires_in <=> other.expires_in
9
- end
10
-
11
- def expired?
12
- expires_in <= Time.now.to_f
13
- end
14
- end
15
- end
@@ -1,3 +0,0 @@
1
- module Eventkit
2
- VERSION = '0.0.4'
3
- end
@@ -1,278 +0,0 @@
1
- require 'support/async_helper'
2
- require 'socket'
3
- require 'eventkit'
4
-
5
- module Eventkit
6
- RSpec.describe EventLoop do
7
- include AsyncHelper
8
-
9
- let!(:event_loop) { EventLoop.new(select_interval: 1 / 100_000) }
10
-
11
- let!(:tcp_server) { TCPServer.new('localhost', 9595) }
12
-
13
- let!(:another_tcp_server) { TCPServer.new('localhost', 9494) }
14
-
15
- let!(:tcp_socket) { TCPSocket.new('localhost', 9595) }
16
-
17
- let!(:another_tcp_socket) { TCPSocket.new('localhost', 9494) }
18
-
19
- after do
20
- tcp_server.close
21
- another_tcp_server.close
22
- tcp_socket.close
23
- another_tcp_socket.close
24
- end
25
-
26
- it 'allows to start and stop the event loop' do
27
- verifier = double(did_stop: nil)
28
-
29
- event_loop.on_next_tick do
30
- event_loop.stop
31
- verifier.did_stop
32
- end
33
-
34
- event_loop.start
35
-
36
- expect(verifier).to have_received(:did_stop)
37
- end
38
-
39
- it 'does not allow to start the event loop once it has started' do
40
- expect do
41
- listener = double(:listener)
42
-
43
- allow(listener).to receive(:handle_event) do |_io|
44
- event_loop.start
45
- end
46
-
47
- event_loop.register_write(tcp_socket, &listener.method(:handle_event))
48
-
49
- event_loop.start
50
- end.to raise_error(EventLoopAlreadyStartedError)
51
- end
52
-
53
- it 'allows to restart the event loop' do
54
- expect do |block|
55
- event_loop.register_write(tcp_socket) do |io|
56
- block.to_proc.call(:once)
57
- event_loop.stop
58
- event_loop.deregister_write(io)
59
-
60
- event_loop.register_write(another_tcp_socket) do |io|
61
- block.to_proc.call(:twice)
62
- event_loop.stop
63
- event_loop.deregister_write(io)
64
- end
65
- event_loop.start
66
- end
67
-
68
- event_loop.start
69
- end.to yield_successive_args(:once, :twice)
70
- end
71
-
72
- it 'notifies when a single read operation is ready' do
73
- fake_server = double(to_io: tcp_server, connection_read_ready: nil)
74
-
75
- event_loop.register_read(fake_server, &fake_server.method(:connection_read_ready))
76
-
77
- event_loop.tick
78
-
79
- expect(fake_server).to have_received(:connection_read_ready).once.with(fake_server)
80
- end
81
-
82
- it 'notifies when a single write operation is ready' do
83
- fake_socket = double(to_io: tcp_socket, connection_write_ready: nil)
84
-
85
- event_loop.register_write(fake_socket, &fake_socket.method(:connection_write_ready))
86
-
87
- event_loop.tick
88
-
89
- expect(fake_socket).to have_received(:connection_write_ready).once.with(fake_socket)
90
- end
91
-
92
- it 'notifies when multiple write operations are ready' do
93
- fake_socket = double(to_io: tcp_socket, connection_write_ready: nil)
94
- another_fake_socket = double(to_io: another_tcp_socket, ready_to_write: nil)
95
-
96
- event_loop.register_write(fake_socket, &fake_socket.method(:connection_write_ready))
97
- event_loop.register_write(another_fake_socket, &another_fake_socket.method(:ready_to_write))
98
-
99
- event_loop.tick
100
-
101
- expect(fake_socket).to have_received(:connection_write_ready).once.with(fake_socket)
102
- expect(another_fake_socket).to have_received(:ready_to_write).once.with(another_fake_socket)
103
- end
104
-
105
- it 'notifies when multiple read operations are ready' do
106
- fake_server = double(to_io: tcp_server, connection_read_ready: nil)
107
- another_fake_server = double(to_io: another_tcp_server, new_connection: nil)
108
-
109
- event_loop.register_read(fake_server, &fake_server.method(:connection_read_ready))
110
- event_loop.register_read(another_fake_server, &another_fake_server.method(:new_connection))
111
-
112
- event_loop.tick
113
-
114
- expect(fake_server).to have_received(:connection_read_ready).once.with(fake_server)
115
- expect(another_fake_server).to have_received(:new_connection).once.with(another_fake_server)
116
- end
117
-
118
- it 'allows an object to register reads on multiple io objects' do
119
- listener = double(connection_read_ready: nil, another_connection: nil)
120
-
121
- event_loop.register_read(tcp_server, &listener.method(:connection_read_ready))
122
- event_loop.register_read(another_tcp_server, &listener.method(:another_connection))
123
-
124
- expect(listener).to receive(:connection_read_ready).once.with(tcp_server)
125
- expect(listener).to receive(:another_connection).once.with(another_tcp_server)
126
-
127
- event_loop.tick
128
- end
129
-
130
- it 'allows an object to register writes on multiple io objects' do
131
- listener = double(one_ready_to_write: nil, another_ready_to_write: nil)
132
-
133
- event_loop.register_write(tcp_socket, &listener.method(:one_ready_to_write))
134
- event_loop.register_write(another_tcp_socket, &listener.method(:another_ready_to_write))
135
-
136
- expect(listener).to receive(:one_ready_to_write).once.with(tcp_socket)
137
- expect(listener).to receive(:another_ready_to_write).once.with(another_tcp_socket)
138
-
139
- event_loop.tick
140
- end
141
-
142
- it 'allows to register multiple read handlers on a single io object' do
143
- listener = double(connection_read_ready: nil)
144
- another_listener = double(new_connection: nil)
145
-
146
- event_loop.register_read(tcp_server, &listener.method(:connection_read_ready))
147
- event_loop.register_read(tcp_server, &another_listener.method(:new_connection))
148
-
149
- expect(listener).to receive(:connection_read_ready).once.with(tcp_server)
150
- expect(another_listener).to receive(:new_connection).once.with(tcp_server)
151
-
152
- event_loop.tick
153
- end
154
-
155
- it 'allows to register multiple write handlers on a single io object' do
156
- listener = double(connection_write_ready: nil)
157
- another_listener = double(ready_to_write: nil)
158
-
159
- event_loop.register_write(tcp_socket, &listener.method(:connection_write_ready))
160
- event_loop.register_write(tcp_socket, &another_listener.method(:ready_to_write))
161
-
162
- expect(listener).to receive(:connection_write_ready).once.with(tcp_socket)
163
- expect(another_listener).to receive(:ready_to_write).once.with(tcp_socket)
164
-
165
- event_loop.tick
166
- end
167
-
168
- it 'allows to deregister read handlers' do
169
- listener = double(connection_read_ready: nil)
170
- handler = listener.method(:connection_read_ready).to_proc
171
-
172
- event_loop.register_read(tcp_server, &handler)
173
- event_loop.deregister_read(tcp_server, &handler)
174
-
175
- expect(listener).not_to receive(:connection_read_ready)
176
-
177
- event_loop.tick
178
- end
179
-
180
- it 'allows to deregister write handlers' do
181
- listener = double(connection_write_ready: nil)
182
-
183
- handler = listener.method(:connection_write_ready).to_proc
184
-
185
- event_loop.register_write(tcp_socket, &handler)
186
- event_loop.deregister_write(tcp_socket, handler)
187
-
188
- expect(listener).not_to receive(:connection_write_ready)
189
-
190
- event_loop.tick
191
- end
192
-
193
- it 'deregisters all write handlers for an io object' do
194
- listener = double(connection_write_ready: nil, another_write_event: nil)
195
-
196
- first_handler = listener.method(:connection_write_ready).to_proc
197
- second_handler = listener.method(:another_write_event).to_proc
198
-
199
- event_loop.register_write(tcp_socket, &first_handler)
200
- event_loop.register_write(tcp_socket, &second_handler)
201
-
202
- event_loop.deregister_write(tcp_socket)
203
-
204
- expect(listener).not_to receive(:connection_write_ready)
205
- expect(listener).not_to receive(:another_event)
206
-
207
- event_loop.tick
208
- end
209
-
210
- it 'deregisters all read handlers for an io object' do
211
- listener = double(connection_read_ready: nil, another_read_event: nil)
212
-
213
- first_handler = listener.method(:connection_read_ready).to_proc
214
- second_handler = listener.method(:another_read_event).to_proc
215
-
216
- connection = tcp_server.accept
217
- connection.write('hello world')
218
-
219
- event_loop.register_read(tcp_socket, &first_handler)
220
- event_loop.register_read(tcp_socket, &second_handler)
221
-
222
- event_loop.deregister_read(tcp_socket)
223
-
224
- expect(listener).not_to receive(:connection_read_ready)
225
- expect(listener).not_to receive(:another_event)
226
-
227
- event_loop.tick
228
- end
229
-
230
- it 'allows to register timers which will executed in order' do
231
- listener = double(timer_expired_a: nil,
232
- timer_expired_b: nil,
233
- timer_expired_c: nil,
234
- timer_expired_d: nil)
235
-
236
- event_loop.register_timer(run_in: 2, &listener.method(:timer_expired_a))
237
-
238
- event_loop.register_timer(run_in: 3, &listener.method(:timer_expired_b))
239
-
240
- event_loop.register_timer(run_in: 1, &listener.method(:timer_expired_c))
241
-
242
- event_loop.register_timer(run_in: 5, &listener.method(:timer_expired_d))
243
-
244
- sleep(3.1)
245
-
246
- event_loop.tick
247
-
248
- expect(listener).to have_received(:timer_expired_c).ordered.once
249
- expect(listener).to have_received(:timer_expired_a).ordered.once
250
- expect(listener).to have_received(:timer_expired_b).ordered.once
251
- expect(listener).to_not have_received(:timer_expired_d)
252
- end
253
-
254
- it 'deregister timers as soon as they have expired' do
255
- listener = double(timer_expired: nil)
256
-
257
- event_loop.register_timer(run_in: 1, &listener.method(:timer_expired))
258
-
259
- sleep(2)
260
-
261
- event_loop.tick
262
- event_loop.tick
263
-
264
- expect(listener).to have_received(:timer_expired).once
265
- end
266
-
267
- it 'allows to schedule code to be run on the next tick' do
268
- listener = double(on_next_tick: nil)
269
-
270
- event_loop.on_next_tick(&listener.method(:on_next_tick))
271
-
272
- event_loop.tick
273
-
274
- expect(listener).to have_received(:on_next_tick).once
275
- end
276
- end
277
- end
278
-
@@ -1,40 +0,0 @@
1
- module AsyncHelper
2
- # Instead of waiting an specific an amount of time and then
3
- # asserting for a certain behaviour, this test helper polls for an assertion
4
- # success every X number of seconds (configurable as interval).
5
- # The test will fail if the assertion doesn't pass after Y number of
6
- # seconds (configurable as timeout).
7
- def eventually(options = {})
8
- timeout = options[:timeout] || 1 # seconds
9
- interval = options[:interval] || 0.0001 # seconds
10
- time_limit = Time.now + timeout
11
-
12
- loop do
13
- begin
14
- yield
15
- rescue RSpec::Expectations::ExpectationNotMetError => error
16
-
17
- end
18
-
19
- return if error.nil?
20
-
21
- fail error if Time.now >= time_limit
22
- sleep interval
23
- end
24
- end
25
-
26
- # Same behaviour as eventually, but decided to change the method name to make
27
- # it more clear that this is focused on 'synchronizing' the test with the application
28
- def wait_until(options = {}, &block)
29
- eventually(options, &block)
30
- end
31
-
32
- # Small wrapper around sleep
33
- def on_timeout(options = {})
34
- timeout = options[:timeout] || 0.5
35
-
36
- sleep timeout
37
-
38
- yield
39
- end
40
- end