hungryblank-event_utils 0.0.2

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.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Paolo Negri
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,34 @@
1
+ = event_utils
2
+
3
+ EventUtils is meant to provide modules and classes to help building services
4
+ on top of EventMachine without having to cope with some of the mechnics of
5
+ eventmachine itself.
6
+
7
+ the first implemented facility is EventUtils::DeferredLoop
8
+
9
+ it makes possible to perform action on groups of deferrable objects in an
10
+ intuitive way, and without having to take care of starting/stopping the
11
+ EventMachine reactor
12
+
13
+ example:
14
+
15
+ d1 and d2 are two deferrables
16
+ and we want to compare them but the comparaison is only feasible when
17
+ d1 and d2 have both deferred status set.
18
+
19
+ In this case the code will look like
20
+
21
+ require 'event_utils'
22
+ include EventUtils
23
+
24
+ in_deferred_loop do
25
+ waiting_for d1, d2 do
26
+ d1 > d2
27
+ end
28
+ end
29
+
30
+ Check http://assertbuggy.blogspot.com for further informations and tutorials
31
+
32
+ == Copyright
33
+
34
+ Copyright (c) 2009 Paolo Negri. See LICENSE for details.
@@ -0,0 +1,7 @@
1
+ require 'eventmachine'
2
+ Dir.glob(File.dirname(__FILE__) + '/event_utils/**/*.rb').each do |lib|
3
+ require lib
4
+ end
5
+
6
+ module EventUtils
7
+ end
@@ -0,0 +1,93 @@
1
+ module EventUtils
2
+
3
+ class DeferredChildFailure < StandardError
4
+ end
5
+
6
+ class DeferredLoop
7
+
8
+ def self.main_loop
9
+ @main_loop ||= new(:main)
10
+ end
11
+
12
+
13
+ attr_accessor :success, :failure
14
+
15
+ include EM::Deferrable
16
+
17
+ def initialize(main=false)
18
+ self.class.main_loop.wait_for(self) unless main
19
+ @success, @failure = 0, 0
20
+ @waiting_for = []
21
+ end
22
+
23
+ #takes a list of deferrables to wait for before executing the callback
24
+ def waiting_for(*deferrables, &block)
25
+ deferrables.each { |d| wait_for(d) }.size
26
+ callback { block.call } if block_given?
27
+ errback { raise DeferredChildFailure, "#{failure} deferred entities failed" }
28
+ self
29
+ end
30
+
31
+ #callback used by deferrables the loop is waiting for, it increases failure or
32
+ #success depending by the child outcome
33
+ def child_returned(outcome)
34
+ send(outcome.to_s + '=', send(outcome) + 1)
35
+ terminate if complete?
36
+ end
37
+
38
+ #add a deferrable to the list of deferrables to wait for
39
+ def wait_for(deferrable)
40
+ @waiting_for << deferrable
41
+ deferrable.callback { self.child_returned :success }
42
+ deferrable.errback { self.child_returned :failure }
43
+ end
44
+
45
+ private
46
+
47
+ def complete?
48
+ @waiting_for.size == success + failure
49
+ end
50
+
51
+ #sets the deferred status depending by outcomes of children
52
+ #it fails if one or more children failed
53
+ def terminate
54
+ failure == 0 ? self.succeed : self.fail
55
+ end
56
+
57
+ end
58
+
59
+ #Wraps the clode in the provided block in an EM loop if needed
60
+ #
61
+ # in_deferred_loop do
62
+ # your code using deferrables here
63
+ # end
64
+ #
65
+ def in_deferred_loop(&block)
66
+ drive_reactor = !EM.reactor_running?
67
+ if drive_reactor
68
+ EM.run do
69
+ DeferredLoop.main_loop.callback { EM.stop }
70
+ DeferredLoop.main_loop.errback { EM.stop }
71
+ yield
72
+ end
73
+ else
74
+ yield
75
+ end
76
+ end
77
+
78
+ #waits until all the deferrables have the deferred status set and then
79
+ #executes the code in the provided block
80
+ #
81
+ # in_deferred_loop do
82
+ # waiting_for deferrable_1, deferrable_2, ..., deferrable_n do
83
+ # code that needs all the deferrable deferred status set here
84
+ # end
85
+ # end
86
+ #
87
+ def waiting_for(*deferrables, &block)
88
+ deferred_loop = DeferredLoop.new
89
+ deferred_loop.waiting_for(*deferrables, &block)
90
+ deferred_loop
91
+ end
92
+
93
+ end
@@ -0,0 +1,83 @@
1
+ require 'test_helper'
2
+
3
+ include EventUtils
4
+
5
+ class DeferredLoopTest < Test::Unit::TestCase
6
+
7
+ should "add callback end errback to deferrables it's waiting for" do
8
+ deferrable = Mocha::Mock.new
9
+ deferrable.expects(:callback)
10
+ deferrable.expects(:errback)
11
+ deferred_loop = DeferredLoop.new
12
+ deferred_loop.wait_for deferrable
13
+ end
14
+
15
+ should "evaluate completion on child returned" do
16
+ deferred_loop = DeferredLoop.new
17
+ deferred_loop.expects(:complete?)
18
+ deferred_loop.child_returned(:success)
19
+ end
20
+
21
+ should "complete when number of success + failures equal waiting for" do
22
+ deferred_loop = DeferredLoop.new
23
+ deferred_loop.instance_variable_set('@waiting_for', [1, 2, 3])
24
+ deferred_loop.success = 2
25
+ assert !deferred_loop.send(:complete?)
26
+ deferred_loop.failure = 1
27
+ assert deferred_loop.send(:complete?)
28
+ end
29
+
30
+ should "increase success and failure on child_returned" do
31
+ deferred_loop = DeferredLoop.new
32
+ success, failure = deferred_loop.success, deferred_loop.failure
33
+ deferred_loop.child_returned(:success)
34
+ assert_equal success + 1, deferred_loop.success
35
+ assert_equal failure, deferred_loop.failure
36
+ deferred_loop.child_returned(:failure)
37
+ assert_equal failure + 1, deferred_loop.failure
38
+ end
39
+
40
+ should "fail if there are failures" do
41
+ deferred_loop = DeferredLoop.new
42
+ deferred_loop.instance_variable_set('@waiting_for', [1])
43
+ deferred_loop.child_returned(:failure)
44
+ deferred_loop.expects(:fail)
45
+ deferred_loop.send(:terminate)
46
+ end
47
+
48
+ should "succeed if there aren't failures" do
49
+ deferred_loop = DeferredLoop.new
50
+ deferred_loop.instance_variable_set('@waiting_for', [1])
51
+ deferred_loop.child_returned(:success)
52
+ deferred_loop.expects(:succeed)
53
+ deferred_loop.send(:terminate)
54
+ end
55
+
56
+ should "add callback to main loop when EM reactor is not running" do
57
+ EM.expects(:run)
58
+ main_loop = Mocha::Mock.new
59
+ DeferredLoop.stubs(:main_loop).returns(main_loop)
60
+ main_loop.expects(:callback)
61
+ in_deferred_loop {}
62
+ end
63
+
64
+ should "wait for all the deferrables passed to waiting for" do
65
+ EM.stubs(:reactor_running?).returns(true)
66
+ ev_loop = DeferredLoop.new
67
+ a = 1
68
+ b = 2
69
+ ev_loop.expects(:wait_for).with(a)
70
+ ev_loop.expects(:wait_for).with(b)
71
+ ev_loop.waiting_for a, b
72
+ end
73
+
74
+ should "instantiate a new loop on class waiting_for" do
75
+ a = b = nil
76
+ l = lambda { 'bla' }
77
+ deferred_loop = Mocha::Mock.new
78
+ DeferredLoop.expects(:new).returns(deferred_loop)
79
+ deferred_loop.expects(:waiting_for).with(a, b, l)
80
+ EventUtils.waiting_for(a, b, l)
81
+ end
82
+
83
+ end
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'event_utils'
9
+
10
+ class Test::Unit::TestCase
11
+ end
metadata ADDED
@@ -0,0 +1,70 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hungryblank-event_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Paolo Negri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-12 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: eventmachine
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: hungryblank@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ - LICENSE
34
+ files:
35
+ - README.rdoc
36
+ - lib/event_utils
37
+ - lib/event_utils/evented_loop.rb
38
+ - lib/event_utils.rb
39
+ - test/deferred_loop_test.rb
40
+ - test/test_helper.rb
41
+ - LICENSE
42
+ has_rdoc: true
43
+ homepage: http://github.com/hungryblank/event_utils
44
+ post_install_message:
45
+ rdoc_options:
46
+ - --inline-source
47
+ - --charset=UTF-8
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ version:
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ requirements: []
63
+
64
+ rubyforge_project:
65
+ rubygems_version: 1.2.0
66
+ signing_key:
67
+ specification_version: 2
68
+ summary: provides various facilities to help building tools on top of eventmachine
69
+ test_files: []
70
+