em-synchrony 1.0.3 → 1.0.4
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 +7 -0
- data/README.md +4 -1
- data/em-synchrony.gemspec +2 -1
- data/lib/em-synchrony.rb +8 -0
- data/lib/em-synchrony/activerecord.rb +42 -1
- data/lib/em-synchrony/amqp.rb +3 -3
- data/lib/em-synchrony/connection_pool.rb +11 -0
- data/lib/em-synchrony/em-hiredis.rb +57 -43
- data/lib/em-synchrony/mechanize.rb +27 -0
- data/lib/em-synchrony/tcpsocket.rb +12 -3
- data/spec/amqp_spec.rb +7 -9
- data/spec/connection_pool_spec.rb +46 -1
- data/spec/helper/all.rb +1 -6
- data/spec/helper/core.rb +6 -0
- data/spec/tcpsocket_spec.rb +84 -10
- metadata +16 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c9fce19d87bacaaddaf2d367cf360ddc1b84c7b1
|
4
|
+
data.tar.gz: 61be19297e6ee682210f7275ef29085060ade75f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f963c206f3d8e4fe10bb4c1b67494915b65ae1a2b8a4c2551e51e8ee651c3dae2edc188452de23e92646990c7b1dee45232e8688014592ba7fa162a1b431a236
|
7
|
+
data.tar.gz: b2aac7705b2c345c1f9607443567c10f18edc190a0070193713d89b69e5d5f31f07d3746da0c6091c03472841431064bc7062be955f0d9040e93ff1769235b6b
|
data/README.md
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
# EM-Synchrony
|
2
2
|
|
3
|
+
[](http://rubygems.org/gems/em-synchrony)
|
4
|
+
[](https://github.com/igrigorik/ga-beacon)
|
5
|
+
|
3
6
|
Collection of convenience classes and primitives to help untangle evented code, plus a number of patched EM clients to make them Fiber aware. To learn more, please see: [Untangling Evented Code with Ruby Fibers](http://www.igvita.com/2010/03/22/untangling-evented-code-with-ruby-fibers).
|
4
7
|
|
5
8
|
* Fiber aware ConnectionPool with sync/async query support
|
@@ -171,4 +174,4 @@ result = Widget.all.to_a
|
|
171
174
|
|
172
175
|
# License
|
173
176
|
|
174
|
-
The MIT License - Copyright (c) 2011 Ilya Grigorik
|
177
|
+
The MIT License - Copyright (c) 2011 Ilya Grigorik
|
data/em-synchrony.gemspec
CHANGED
@@ -3,11 +3,12 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "em-synchrony"
|
6
|
-
s.version = "1.0.
|
6
|
+
s.version = "1.0.4"
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Ilya Grigorik"]
|
9
9
|
s.email = ["ilya@igvita.com"]
|
10
10
|
s.homepage = "http://github.com/igrigorik/em-synchrony"
|
11
|
+
s.license = "MIT"
|
11
12
|
s.summary = %q{Fiber aware EventMachine libraries}
|
12
13
|
s.description = s.summary
|
13
14
|
|
data/lib/em-synchrony.rb
CHANGED
@@ -135,5 +135,13 @@ module EventMachine
|
|
135
135
|
def self.gets
|
136
136
|
EventMachine::Synchrony::Keyboard.new.gets
|
137
137
|
end
|
138
|
+
|
139
|
+
# Interrupt current fiber to give chance to other fibers
|
140
|
+
#
|
141
|
+
def self.interrupt
|
142
|
+
fiber = Fiber.current
|
143
|
+
EM.next_tick { fiber.resume }
|
144
|
+
Fiber.yield
|
145
|
+
end
|
138
146
|
end
|
139
147
|
end
|
@@ -66,6 +66,47 @@ module EM::Synchrony
|
|
66
66
|
def decrement_open_transactions
|
67
67
|
real_connection.open_transactions -= 1
|
68
68
|
end
|
69
|
+
|
70
|
+
def current_transaction #:nodoc:
|
71
|
+
@transaction[Fiber.current.object_id] || @closed_transaction
|
72
|
+
end
|
73
|
+
|
74
|
+
def transaction_open?
|
75
|
+
current_transaction.open?
|
76
|
+
end
|
77
|
+
|
78
|
+
def begin_transaction(options = {}) #:nodoc:
|
79
|
+
set_current_transaction(current_transaction.begin(options))
|
80
|
+
end
|
81
|
+
|
82
|
+
def commit_transaction #:nodoc:
|
83
|
+
set_current_transaction(current_transaction.commit)
|
84
|
+
end
|
85
|
+
|
86
|
+
def rollback_transaction #:nodoc:
|
87
|
+
set_current_transaction(current_transaction.rollback)
|
88
|
+
end
|
89
|
+
|
90
|
+
def reset_transaction #:nodoc:
|
91
|
+
@transaction = {}
|
92
|
+
@closed_transaction = ::ActiveRecord::ConnectionAdapters::ClosedTransaction.new(self)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Register a record with the current transaction so that its after_commit and after_rollback callbacks
|
96
|
+
# can be called.
|
97
|
+
def add_transaction_record(record)
|
98
|
+
current_transaction.add_record(record)
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def set_current_transaction(t)
|
104
|
+
if t == @closed_transaction
|
105
|
+
@transaction.delete(Fiber.current.object_id)
|
106
|
+
else
|
107
|
+
@transaction[Fiber.current.object_id] = t
|
108
|
+
end
|
109
|
+
end
|
69
110
|
end
|
70
111
|
|
71
112
|
class ConnectionPool < EM::Synchrony::ConnectionPool
|
@@ -100,4 +141,4 @@ module EM::Synchrony
|
|
100
141
|
end
|
101
142
|
end
|
102
143
|
end
|
103
|
-
end
|
144
|
+
end
|
data/lib/em-synchrony/amqp.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
begin
|
2
2
|
require "amqp"
|
3
3
|
require "amq/protocol"
|
4
|
-
rescue LoadError
|
4
|
+
rescue LoadError
|
5
5
|
raise "Missing EM-Synchrony dependency: gem install amqp"
|
6
6
|
end
|
7
7
|
|
@@ -22,7 +22,7 @@ module EventMachine
|
|
22
22
|
if fiber == Fiber.current
|
23
23
|
return *args
|
24
24
|
else
|
25
|
-
fiber.resume
|
25
|
+
fiber.resume(*args)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -54,7 +54,7 @@ module EventMachine
|
|
54
54
|
def #{type}(name = 'amq.#{type}', opts = {})
|
55
55
|
if exchange = find_exchange(name)
|
56
56
|
extended_opts = Exchange.add_default_options(:#{type}, name, opts, nil)
|
57
|
-
validate_parameters_match!(exchange, extended_opts)
|
57
|
+
validate_parameters_match!(exchange, extended_opts, :exchange)
|
58
58
|
exchange
|
59
59
|
else
|
60
60
|
register_exchange(Exchange.new(self, :#{type}, name, opts))
|
@@ -27,6 +27,17 @@ module EventMachine
|
|
27
27
|
release(f) if not async
|
28
28
|
end
|
29
29
|
end
|
30
|
+
|
31
|
+
# Returns current pool utilization.
|
32
|
+
#
|
33
|
+
# @return [Hash] Current utilization.
|
34
|
+
def pool_status
|
35
|
+
{
|
36
|
+
available: @available.size,
|
37
|
+
reserved: @reserved.size,
|
38
|
+
pending: @pending.size
|
39
|
+
}
|
40
|
+
end
|
30
41
|
|
31
42
|
private
|
32
43
|
|
@@ -6,94 +6,108 @@ end
|
|
6
6
|
|
7
7
|
module EventMachine
|
8
8
|
module Hiredis
|
9
|
-
|
9
|
+
|
10
10
|
def self.connect(uri = nil)
|
11
11
|
client = setup(uri)
|
12
12
|
EM::Synchrony.sync client.connect
|
13
13
|
client
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
class Client
|
17
|
+
def pubsub
|
18
|
+
return @pubsub if @pubsub
|
19
|
+
|
20
|
+
client = PubsubClient.new(@host, @port, @password, @db)
|
21
|
+
EM::Synchrony.sync client.connect
|
22
|
+
@pubsub = client
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class BaseClient
|
17
27
|
def self.connect(host = 'localhost', port = 6379)
|
18
28
|
conn = new(host, port)
|
19
29
|
EM::Synchrony.sync conn.connect
|
20
30
|
conn
|
21
31
|
end
|
22
|
-
|
32
|
+
|
23
33
|
def connect
|
34
|
+
@auto_reconnect = true
|
24
35
|
@connection = EM.connect(@host, @port, Connection, @host, @port)
|
25
|
-
|
36
|
+
|
26
37
|
@connection.on(:closed) do
|
27
38
|
if @connected
|
28
|
-
@defs.each { |d| d.fail("Redis disconnected") }
|
39
|
+
@defs.each { |d| d.fail(Error.new("Redis disconnected")) }
|
29
40
|
@defs = []
|
30
41
|
@deferred_status = nil
|
31
42
|
@connected = false
|
32
|
-
|
33
|
-
|
34
|
-
reconnect
|
43
|
+
if @auto_reconnect
|
44
|
+
# Next tick avoids reconnecting after for example EM.stop
|
45
|
+
EM.next_tick { reconnect }
|
35
46
|
end
|
47
|
+
emit(:disconnected)
|
48
|
+
EM::Hiredis.logger.info("#{@connection} Disconnected")
|
36
49
|
else
|
37
|
-
|
38
|
-
|
50
|
+
if @auto_reconnect
|
51
|
+
@reconnect_failed_count += 1
|
52
|
+
@reconnect_timer = EM.add_timer(EM::Hiredis.reconnect_timeout) {
|
53
|
+
@reconnect_timer = nil
|
54
|
+
reconnect
|
55
|
+
}
|
56
|
+
emit(:reconnect_failed, @reconnect_failed_count)
|
57
|
+
EM::Hiredis.logger.info("#{@connection} Reconnect failed")
|
58
|
+
|
59
|
+
if @reconnect_failed_count >= 4
|
60
|
+
emit(:failed)
|
61
|
+
self.fail(Error.new("Could not connect after 4 attempts"))
|
62
|
+
end
|
39
63
|
end
|
40
64
|
end
|
41
65
|
end
|
42
|
-
|
66
|
+
|
43
67
|
@connection.on(:connected) do
|
44
68
|
Fiber.new do
|
45
69
|
@connected = true
|
46
|
-
|
70
|
+
@reconnect_failed_count = 0
|
71
|
+
@failed = false
|
72
|
+
|
73
|
+
select(@db) unless @db == 0
|
47
74
|
auth(@password) if @password
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
75
|
+
|
76
|
+
@command_queue.each do |df, command, args|
|
77
|
+
@connection.send_command(command, args)
|
78
|
+
@defs.push(df)
|
79
|
+
end
|
80
|
+
@command_queue = []
|
81
|
+
|
82
|
+
emit(:connected)
|
83
|
+
EM::Hiredis.logger.info("#{@connection} Connected")
|
52
84
|
succeed
|
53
|
-
|
85
|
+
|
54
86
|
if @reconnecting
|
55
87
|
@reconnecting = false
|
56
88
|
emit(:reconnected)
|
57
89
|
end
|
58
90
|
end.resume
|
59
91
|
end
|
60
|
-
|
92
|
+
|
61
93
|
@connection.on(:message) do |reply|
|
62
94
|
if RuntimeError === reply
|
63
95
|
raise "Replies out of sync: #{reply.inspect}" if @defs.empty?
|
64
96
|
deferred = @defs.shift
|
65
|
-
|
97
|
+
error = RedisError.new(reply.message)
|
98
|
+
error.redis_error = reply
|
99
|
+
deferred.fail(error) if deferred
|
66
100
|
else
|
67
|
-
|
68
|
-
kind, subscription, d1, d2 = *reply
|
69
|
-
|
70
|
-
case kind.to_sym
|
71
|
-
when :message
|
72
|
-
emit(:message, subscription, d1)
|
73
|
-
when :pmessage
|
74
|
-
emit(:pmessage, subscription, d1, d2)
|
75
|
-
end
|
76
|
-
else
|
77
|
-
if @defs.empty?
|
78
|
-
if @monitoring
|
79
|
-
emit(:monitor, reply)
|
80
|
-
else
|
81
|
-
raise "Replies out of sync: #{reply.inspect}"
|
82
|
-
end
|
83
|
-
else
|
84
|
-
deferred = @defs.shift
|
85
|
-
deferred.succeed(reply) if deferred
|
86
|
-
end
|
87
|
-
end
|
101
|
+
handle_reply(reply)
|
88
102
|
end
|
89
103
|
end
|
90
|
-
|
104
|
+
|
91
105
|
@connected = false
|
92
106
|
@reconnecting = false
|
93
|
-
|
107
|
+
|
94
108
|
return self
|
95
109
|
end
|
96
|
-
|
110
|
+
|
97
111
|
alias :old_method_missing :method_missing
|
98
112
|
def method_missing(sym, *args)
|
99
113
|
EM::Synchrony.sync old_method_missing(sym, *args)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
|
3
|
+
module EventMachine
|
4
|
+
module Synchrony
|
5
|
+
class Mechanize < ::Mechanize
|
6
|
+
def initialize(*args, &blk)
|
7
|
+
super
|
8
|
+
@agent.instance_variable_get(:@http).singleton_class.send(:include, DeferedNetHttpPersistentRequest)
|
9
|
+
end
|
10
|
+
|
11
|
+
module DeferedNetHttpPersistentRequest
|
12
|
+
def self.included(base)
|
13
|
+
base.class_eval do
|
14
|
+
alias :request_without_defer :request
|
15
|
+
alias :request :request_with_defer
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def request_with_defer(*args, &blk)
|
20
|
+
EM::Synchrony.defer do
|
21
|
+
request_without_defer(*args, &blk)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -85,7 +85,13 @@ module EventMachine
|
|
85
85
|
def read(num_bytes = nil, dest = nil)
|
86
86
|
handle_read(:read, num_bytes, dest)
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
|
+
def read_nonblock(maxlen, dest = nil)
|
90
|
+
raise ArgumentError, "maxlen must be > 0" if !maxlen || maxlen <= 0
|
91
|
+
read_bytes = handle_read(:read_nonblock, maxlen, dest)
|
92
|
+
raise EOFError if read_bytes.nil?
|
93
|
+
read_bytes
|
94
|
+
end
|
89
95
|
|
90
96
|
def recv(num_bytes, flags = 0)
|
91
97
|
raise "Unknown flags in recv(): #{flags}" if flags.nonzero?
|
@@ -159,11 +165,14 @@ module EventMachine
|
|
159
165
|
end
|
160
166
|
|
161
167
|
def try_read_data
|
162
|
-
if @read_type == :read
|
168
|
+
if @read_type == :read || @read_type == :read_nonblock
|
169
|
+
nonblocking = @read_type == :read_nonblock
|
163
170
|
unless @remote_closed
|
164
171
|
if @read_bytes
|
165
172
|
# read(n) on an open socket, with >= than n buffered data, returns n data
|
166
|
-
if @in_buff.size >= @read_bytes
|
173
|
+
if (@in_buff.size >= @read_bytes ||
|
174
|
+
(nonblocking && @in_buff.size > 0)) then
|
175
|
+
@in_buff.slice!(0, @read_bytes)
|
167
176
|
# read(n) on an open socket, with < than n buffered data, blocks
|
168
177
|
else :block end
|
169
178
|
else
|
data/spec/amqp_spec.rb
CHANGED
@@ -54,15 +54,13 @@ describe EM::Synchrony::AMQP do
|
|
54
54
|
exchange = EM::Synchrony::AMQP::Exchange.new(channel, :fanout, "test.em-synchrony.exchange")
|
55
55
|
exchange.should be_kind_of(EventMachine::Synchrony::AMQP::Exchange)
|
56
56
|
|
57
|
-
direct
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
topic.should be_kind_of(EventMachine::Synchrony::AMQP::Exchange)
|
65
|
-
headers.should be_kind_of(EventMachine::Synchrony::AMQP::Exchange)
|
57
|
+
[:direct, :fanout, :topic, :headers].each do |type|
|
58
|
+
# Exercise cached exchange code path
|
59
|
+
2.times.map { channel.send(type, "test.em-synchrony.#{type}") }.each do |ex|
|
60
|
+
ex.should be_kind_of(EventMachine::Synchrony::AMQP::Exchange)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
66
64
|
EM.stop
|
67
65
|
end
|
68
66
|
end
|
@@ -126,4 +126,49 @@ describe EventMachine::Synchrony::ConnectionPool do
|
|
126
126
|
end
|
127
127
|
end
|
128
128
|
|
129
|
-
|
129
|
+
describe '#pool_status' do
|
130
|
+
it 'should return right initial size' do
|
131
|
+
(1..10).each do |count|
|
132
|
+
pool = EventMachine::Synchrony::ConnectionPool.new(size: count) { }
|
133
|
+
status = pool.pool_status
|
134
|
+
expect(status).to include available: count
|
135
|
+
expect(status).to include reserved: 0
|
136
|
+
expect(status).to include pending: 0
|
137
|
+
end
|
138
|
+
end
|
139
|
+
it 'should return up-to-date statusrmation' do
|
140
|
+
sleep = 0.5
|
141
|
+
count = 5
|
142
|
+
EM.run do
|
143
|
+
pool = EM::Synchrony::ConnectionPool.new(size: count) do
|
144
|
+
-> { EM::Synchrony.sleep(sleep) }
|
145
|
+
end
|
146
|
+
(1..count).each do |used|
|
147
|
+
Fiber.new { pool.call }.resume
|
148
|
+
status = pool.pool_status
|
149
|
+
expect(status).to include available: count - used
|
150
|
+
expect(status).to include reserved: used
|
151
|
+
expect(status).to include pending: 0
|
152
|
+
end
|
153
|
+
(1..count).each do |used|
|
154
|
+
Fiber.new { pool.call }.resume
|
155
|
+
status = pool.pool_status
|
156
|
+
expect(status).to include available: 0
|
157
|
+
expect(status).to include reserved: count
|
158
|
+
expect(status).to include pending: used
|
159
|
+
end
|
160
|
+
Fiber.new {
|
161
|
+
EM::Synchrony.sleep(sleep + 0.1)
|
162
|
+
expect(pool.pool_status).to include pending: 0
|
163
|
+
|
164
|
+
EM::Synchrony.sleep(sleep + 0.1)
|
165
|
+
status = pool.pool_status
|
166
|
+
expect(status).to include available: count
|
167
|
+
expect(status).to include reserved: 0
|
168
|
+
expect(status).to include pending: 0
|
169
|
+
EM.stop
|
170
|
+
}.resume
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
data/spec/helper/all.rb
CHANGED
@@ -1,9 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'rspec'
|
3
|
-
require 'pp'
|
4
|
-
|
5
|
-
require 'lib/em-synchrony'
|
6
|
-
require 'lib/em-synchrony/em-http'
|
1
|
+
require 'spec/helper/core'
|
7
2
|
require 'lib/em-synchrony/mysql2'
|
8
3
|
require 'lib/em-synchrony/em-remcached'
|
9
4
|
require 'lib/em-synchrony/em-memcache'
|
data/spec/helper/core.rb
ADDED
data/spec/tcpsocket_spec.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "spec/helper/
|
1
|
+
require "spec/helper/core"
|
2
2
|
|
3
3
|
module SendAndClose
|
4
4
|
def post_init
|
@@ -21,15 +21,13 @@ module SendAndKeepOpen
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def tcp_test(server_type, ops={}, &block)
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
EM.stop if ops[:stop]
|
32
|
-
end
|
24
|
+
EventMachine.synchrony do
|
25
|
+
ops = {:stop => true}.merge ops
|
26
|
+
EM::start_server('localhost', 12345, server_type)
|
27
|
+
@socket = EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
|
28
|
+
@socket.close if ops[:close]
|
29
|
+
block.call
|
30
|
+
EM.stop if ops[:stop]
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
@@ -231,6 +229,82 @@ describe EventMachine::Synchrony::TCPSocket do
|
|
231
229
|
end
|
232
230
|
end
|
233
231
|
|
232
|
+
context '#read_nonblock' do
|
233
|
+
context 'with a positive length argument' do
|
234
|
+
context 'when the connection is open' do
|
235
|
+
context 'with greater or equal than the requested data buffered' do
|
236
|
+
it 'returns the requested data and no more' do
|
237
|
+
tcp_test(SendAndKeepOpen) do
|
238
|
+
@socket.read_nonblock(2).size.should eq 2
|
239
|
+
@socket.read_nonblock(1).size.should eq 1
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
context 'with less than the requested data buffered' do
|
244
|
+
it 'returns the available data' do
|
245
|
+
tcp_test(SendAndKeepOpen) do
|
246
|
+
@socket.read_nonblock(10).size.should eq 4
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
251
|
+
context 'when the peer has closed the connection' do
|
252
|
+
context 'with no data buffered' do
|
253
|
+
it 'raises EOFError' do
|
254
|
+
tcp_test(SendAndClose) do
|
255
|
+
@socket.read_nonblock(4).size.should eq 4
|
256
|
+
lambda {
|
257
|
+
@socket.read_nonblock(1)
|
258
|
+
}.should raise_error(EOFError)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
context 'with less than the requested data buffered' do
|
263
|
+
it 'returns the buffered data' do
|
264
|
+
tcp_test(SendAndClose) do
|
265
|
+
@socket.read_nonblock(50).size.should eq 4
|
266
|
+
end
|
267
|
+
end
|
268
|
+
end
|
269
|
+
context 'with greater or equal than the requested data buffered' do
|
270
|
+
it 'returns the requested data and no more' do
|
271
|
+
tcp_test(SendAndClose) do
|
272
|
+
@socket = EventMachine::Synchrony::TCPSocket.new 'localhost', 12345
|
273
|
+
@socket.read_nonblock(2).size.should eq 2
|
274
|
+
end
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
context 'when we closed the connection' do
|
279
|
+
it 'raises IOError' do
|
280
|
+
tcp_test(SendAndKeepOpen, :close => true) do
|
281
|
+
proc {
|
282
|
+
@socket.read_nonblock(4)
|
283
|
+
}.should raise_error(IOError)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
end
|
288
|
+
context 'with a negative length argument' do
|
289
|
+
it 'raises ArgumentError' do
|
290
|
+
tcp_test(SendAndKeepOpen) do
|
291
|
+
proc {
|
292
|
+
@socket.read_nonblock(-10)
|
293
|
+
}.should raise_error(ArgumentError)
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
context 'with a zero length argument' do
|
298
|
+
it 'raises ArgumentError' do
|
299
|
+
tcp_test(SendAndKeepOpen) do
|
300
|
+
proc {
|
301
|
+
@socket.read_nonblock(0)
|
302
|
+
}.should raise_error(ArgumentError)
|
303
|
+
end
|
304
|
+
end
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
234
308
|
context '#recv' do
|
235
309
|
context 'with a length argument' do
|
236
310
|
context 'with a possitive length argument' do
|
metadata
CHANGED
@@ -1,30 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-synchrony
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.4
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Ilya Grigorik
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2015-01-18 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: eventmachine
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: 1.0.0.beta.1
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: 1.0.0.beta.1
|
30
27
|
description: Fiber aware EventMachine libraries
|
@@ -34,8 +31,8 @@ executables: []
|
|
34
31
|
extensions: []
|
35
32
|
extra_rdoc_files: []
|
36
33
|
files:
|
37
|
-
- .gitignore
|
38
|
-
- .rspec
|
34
|
+
- ".gitignore"
|
35
|
+
- ".rspec"
|
39
36
|
- Gemfile
|
40
37
|
- README.md
|
41
38
|
- Rakefile
|
@@ -65,6 +62,7 @@ files:
|
|
65
62
|
- lib/em-synchrony/fiber_iterator.rb
|
66
63
|
- lib/em-synchrony/iterator.rb
|
67
64
|
- lib/em-synchrony/keyboard.rb
|
65
|
+
- lib/em-synchrony/mechanize.rb
|
68
66
|
- lib/em-synchrony/mongo.rb
|
69
67
|
- lib/em-synchrony/mongoid.rb
|
70
68
|
- lib/em-synchrony/mysql2.rb
|
@@ -78,6 +76,7 @@ files:
|
|
78
76
|
- spec/em-mongo_spec.rb
|
79
77
|
- spec/fiber_iterator_spec.rb
|
80
78
|
- spec/helper/all.rb
|
79
|
+
- spec/helper/core.rb
|
81
80
|
- spec/helper/stub-http-server.rb
|
82
81
|
- spec/helper/tolerance_matcher.rb
|
83
82
|
- spec/hiredis_spec.rb
|
@@ -97,28 +96,28 @@ files:
|
|
97
96
|
- spec/thread_spec.rb
|
98
97
|
- spec/timer_spec.rb
|
99
98
|
homepage: http://github.com/igrigorik/em-synchrony
|
100
|
-
licenses:
|
99
|
+
licenses:
|
100
|
+
- MIT
|
101
|
+
metadata: {}
|
101
102
|
post_install_message:
|
102
103
|
rdoc_options: []
|
103
104
|
require_paths:
|
104
105
|
- lib
|
105
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
-
none: false
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ">="
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
112
|
-
none: false
|
113
112
|
requirements:
|
114
|
-
- -
|
113
|
+
- - ">="
|
115
114
|
- !ruby/object:Gem::Version
|
116
115
|
version: '0'
|
117
116
|
requirements: []
|
118
117
|
rubyforge_project: em-synchrony
|
119
|
-
rubygems_version:
|
118
|
+
rubygems_version: 2.4.3
|
120
119
|
signing_key:
|
121
|
-
specification_version:
|
120
|
+
specification_version: 4
|
122
121
|
summary: Fiber aware EventMachine libraries
|
123
122
|
test_files:
|
124
123
|
- spec/activerecord_spec.rb
|
@@ -129,6 +128,7 @@ test_files:
|
|
129
128
|
- spec/em-mongo_spec.rb
|
130
129
|
- spec/fiber_iterator_spec.rb
|
131
130
|
- spec/helper/all.rb
|
131
|
+
- spec/helper/core.rb
|
132
132
|
- spec/helper/stub-http-server.rb
|
133
133
|
- spec/helper/tolerance_matcher.rb
|
134
134
|
- spec/hiredis_spec.rb
|
@@ -147,4 +147,3 @@ test_files:
|
|
147
147
|
- spec/tcpsocket_spec.rb
|
148
148
|
- spec/thread_spec.rb
|
149
149
|
- spec/timer_spec.rb
|
150
|
-
has_rdoc:
|