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 +1 -0
- data/lib/em-easy/extensions/enumerable.rb +5 -0
- data/lib/em-easy/extensions/kernel.rb +5 -0
- data/lib/em-easy.rb +71 -0
- data/spec/integration_spec.rb +56 -0
- data/spec/spec_helper.rb +3 -0
- metadata +83 -0
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
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
|
data/spec/spec_helper.rb
ADDED
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
|