em-easy 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.
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,5 @@
1
+ module Enumerable
2
+ def async
3
+ Async::Enumerator.new self
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Kernel
2
+ def wait(object)
3
+ Async.wait object
4
+ end
5
+ end
data/lib/em-easy.rb ADDED
@@ -0,0 +1,71 @@
1
+ require "fiber"
2
+ require "eventmachine"
3
+ require "em-easy/extensions/kernel"
4
+ require "em-easy/extensions/enumerable"
5
+
6
+ Fiber = Rubinius::Fiber if defined? Rubinius
7
+
8
+ module Async
9
+ extend self
10
+ attr_reader :evented_loop
11
+
12
+ class Enumerator
13
+ include Enumerable
14
+
15
+ def initialize(collection)
16
+ @collection = collection
17
+ @total = collection.size
18
+ end
19
+
20
+ def each(&block)
21
+ @finished = 0
22
+ @block = block
23
+ iterate_collection = proc do
24
+ @collection.each do |it|
25
+ if it.respond_to? :callback
26
+ it.callback {|result| finished result }
27
+ else
28
+ finished it
29
+ end
30
+ end
31
+ end
32
+ Async.evented_loop.resume :block => iterate_collection, :smart => true
33
+ end
34
+
35
+ private
36
+
37
+ def finished(result)
38
+ @block.call result
39
+ @finished += 1
40
+ Async.send :next_iteration, Fiber.yield(@collection) if @finished == @total
41
+ end
42
+ end
43
+
44
+ @evented_loop = Fiber.new do
45
+ EM.run { next_iteration }
46
+ end
47
+
48
+ def wait(object)
49
+ handle_callback = proc do
50
+ object.callback {|*args| next_iteration Fiber.yield(*args) }
51
+ end
52
+ @evented_loop.resume :block => handle_callback, :smart => true
53
+ end
54
+
55
+ private
56
+
57
+ def next_iteration(options=nil)
58
+ block = options && options[:block]
59
+
60
+ if block && options[:smart]
61
+ block.call
62
+ else
63
+ instructions = Fiber.yield(block && block.call)
64
+ EM.next_tick do
65
+ next_iteration instructions
66
+ end
67
+ end
68
+ end
69
+
70
+ @evented_loop.resume
71
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path("../spec_helper", __FILE__)
2
+ require "em-http"
3
+ require "benchmark"
4
+
5
+ describe Async do
6
+ def request
7
+ EM::HttpRequest.new("http://www.postrank.com")
8
+ end
9
+
10
+ def time
11
+ Benchmark.realtime { yield }
12
+ end
13
+
14
+ def time_of_couple_serial_requests
15
+ time { 2.times { wait request.get }}
16
+ end
17
+
18
+ it "should let use EM-operations outside EM.run block" do
19
+ expect { request.get }.to_not raise_error
20
+ end
21
+
22
+ it "should not block async operations" do
23
+ time { request.get }.should be < 0.01
24
+ end
25
+
26
+ it "#wait should block until async operation returns" do
27
+ time { wait request.get }.should be > 0.05
28
+ end
29
+
30
+ it '#wait should return result of async operation' do
31
+ wait(request.get).response.should include("<!DOCTYPE html>")
32
+ end
33
+
34
+ it "#wait should not block other async operations" do
35
+ batch_duration = time { Array.new(5) { request.get }.map {|it| wait it }}
36
+ batch_duration.should be < time_of_couple_serial_requests
37
+ end
38
+
39
+ it "should iterate over async enumerable yielding results of async operations" do
40
+ Array.new(5) { request.get }.async.each do |it|
41
+ it.response.should include("<!DOCTYPE html>")
42
+ end
43
+ end
44
+
45
+ it "should iterate over async enumerable via transparent callbacks" do
46
+ time { Array.new(5) { request.get }.async.map do |it|
47
+ it.response
48
+ end }.should be < time_of_couple_serial_requests
49
+ end
50
+
51
+ it "should handle mixed array with non-deferrable and deferrable objects" do
52
+ result = [request.get, "hey"].async.to_a
53
+ result[0].should == "hey"
54
+ result[1].response.should include("<!DOCTYPE html>")
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
2
+ require "em-easy"
3
+ require "rspec"
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: em-easy
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 1
9
+ version: 0.1.1
10
+ platform: ruby
11
+ authors:
12
+ - brainopia
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-11-07 00:00:00 +03:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: eventmachine
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ~>
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ - 12
31
+ - 10
32
+ version: 0.12.10
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description: Asynchronous programming (based on EventMachine) without trouble of callbacks
36
+ email: ravwar@gmail.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files: []
42
+
43
+ files:
44
+ - VERSION
45
+ - lib/em-easy.rb
46
+ - lib/em-easy/extensions/enumerable.rb
47
+ - lib/em-easy/extensions/kernel.rb
48
+ - spec/integration_spec.rb
49
+ - spec/spec_helper.rb
50
+ has_rdoc: true
51
+ homepage: http://github.com/brainopia/em-easy
52
+ licenses: []
53
+
54
+ post_install_message:
55
+ rdoc_options: []
56
+
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ">="
71
+ - !ruby/object:Gem::Version
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ requirements: []
76
+
77
+ rubyforge_project: em-easy
78
+ rubygems_version: 1.3.7
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Asynchronous programming (based on EventMachine) without trouble of callbacks
82
+ test_files:
83
+ - spec/integration_spec.rb