event_utils 0.2.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.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
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.
data/README.rdoc ADDED
@@ -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.
data/Rakefile ADDED
@@ -0,0 +1,48 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "event_utils"
8
+ gem.summary = %Q{provides various facilities to help building tools on top of eventmachine}
9
+ gem.email = "hungryblank@gmail.com"
10
+ gem.homepage = "http://github.com/hungryblank/event_utils"
11
+ gem.authors = ["Paolo Negri"]
12
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
16
+ end
17
+
18
+ require 'rake/rdoctask'
19
+ Rake::RDocTask.new do |rdoc|
20
+ rdoc.rdoc_dir = 'rdoc'
21
+ rdoc.title = 'event_utils'
22
+ rdoc.options << '--line-numbers' << '--inline-source'
23
+ rdoc.rdoc_files.include('README*')
24
+ rdoc.rdoc_files.include('lib/**/*.rb')
25
+ end
26
+
27
+ require 'rake/testtask'
28
+ Rake::TestTask.new(:test) do |test|
29
+ test.libs << 'lib' << 'test'
30
+ test.pattern = 'test/**/*_test.rb'
31
+ test.verbose = false
32
+ end
33
+
34
+ begin
35
+ require 'rcov/rcovtask'
36
+ Rcov::RcovTask.new do |test|
37
+ test.libs << 'test'
38
+ test.pattern = 'test/**/*_test.rb'
39
+ test.verbose = true
40
+ end
41
+ rescue LoadError
42
+ task :rcov do
43
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
44
+ end
45
+ end
46
+
47
+
48
+ task :default => :test
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{event_utils}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Paolo Negri"]
12
+ s.date = %q{2010-02-20}
13
+ s.email = %q{hungryblank@gmail.com}
14
+ s.extra_rdoc_files = [
15
+ "LICENSE",
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "LICENSE",
21
+ "README.rdoc",
22
+ "Rakefile",
23
+ "VERSION.yml",
24
+ "event_utils.gemspec",
25
+ "lib/event_utils.rb",
26
+ "lib/event_utils/evented_loop.rb",
27
+ "test/deferred_loop_test.rb",
28
+ "test/test_helper.rb"
29
+ ]
30
+ s.homepage = %q{http://github.com/hungryblank/event_utils}
31
+ s.rdoc_options = ["--charset=UTF-8"]
32
+ s.require_paths = ["lib"]
33
+ s.rubygems_version = %q{1.3.5}
34
+ s.summary = %q{provides various facilities to help building tools on top of eventmachine}
35
+ s.test_files = [
36
+ "test/test_helper.rb",
37
+ "test/deferred_loop_test.rb"
38
+ ]
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ else
46
+ end
47
+ else
48
+ end
49
+ end
50
+
@@ -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,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: event_utils
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Paolo Negri
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-20 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: hungryblank@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - LICENSE
24
+ - README.rdoc
25
+ files:
26
+ - .gitignore
27
+ - LICENSE
28
+ - README.rdoc
29
+ - Rakefile
30
+ - VERSION.yml
31
+ - event_utils.gemspec
32
+ - lib/event_utils.rb
33
+ - lib/event_utils/evented_loop.rb
34
+ - test/deferred_loop_test.rb
35
+ - test/test_helper.rb
36
+ has_rdoc: true
37
+ homepage: http://github.com/hungryblank/event_utils
38
+ licenses: []
39
+
40
+ post_install_message:
41
+ rdoc_options:
42
+ - --charset=UTF-8
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.3.5
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: provides various facilities to help building tools on top of eventmachine
64
+ test_files:
65
+ - test/test_helper.rb
66
+ - test/deferred_loop_test.rb