with_connection 0.1.11 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.11
1
+ 0.1.12
@@ -1,10 +1,161 @@
1
+ require 'timeout'
2
+
1
3
  module Dalli
2
4
  class Server
3
- class KAsyncSocket < EventMachine::Synchrony::TCPSocket
4
- def readfull(count)
5
- value = ''
6
- read count, value
7
- value
5
+ # from thrift_cliet-0.8.2/lib/thrift_client/event_machine.rb
6
+ module EventMachineConnection
7
+ GARBAGE_BUFFER_SIZE = 4096 # 4kB
8
+
9
+ include EM::Deferrable
10
+
11
+ def self.connect(host='localhost', port=11211, options={}, &block)
12
+ fiber = Fiber.current
13
+ EM.connect(host, port, self, host, port) do |conn|
14
+ conn.pending_connect_timeout = options[:timeout] || 5
15
+ conn.read_timeout = options[:read_timeout] || 5
16
+ conn.write_timeout = options[:write_timeout] || 5
17
+ end.tap do |connection|
18
+ connection.callback do
19
+ fiber.resume
20
+ end
21
+
22
+ connection.errback do
23
+ fiber.resume
24
+ end
25
+
26
+ Fiber.yield
27
+
28
+ raise Exception, "Unable to connect to #{host}:#{port}" unless connection.connected?
29
+ end
30
+ end
31
+
32
+ def trap
33
+ begin
34
+ yield
35
+ rescue Exception => ex
36
+ puts ex.message
37
+ puts ex.backtrace.join("\n")
38
+ end
39
+ end
40
+
41
+ attr_accessor :read_timeout, :write_timeout
42
+
43
+ def initialize(host, port=9090)
44
+ @host, @port = host, port
45
+ @index = 0
46
+ @disconnected = 'not connected'
47
+ @buf = ''
48
+ end
49
+
50
+ def close
51
+ trap do
52
+ @disconnected = 'closed'
53
+ close_connection(true)
54
+ end
55
+ end
56
+
57
+ def blocking_read(size)
58
+ raise IOError, "lost connection to #{@host}:#{@port}: #{@disconnected}" if @disconnected
59
+ if can_read?(size)
60
+ yank(size)
61
+ else
62
+ raise ArgumentError, "Unexpected state" if @size or @callback
63
+
64
+ timed(self.read_timeout) do
65
+ read_with_callback size
66
+ end
67
+ end
68
+ end
69
+ alias readfull blocking_read
70
+
71
+ # when enough data has been received the callback will return the data to the requesting fiber
72
+ def read_with_callback(size)
73
+ fiber = Fiber.current
74
+
75
+ @size = size
76
+ @callback = proc { |data|
77
+ fiber.resume(data)
78
+ }
79
+
80
+ Fiber.yield
81
+ end
82
+
83
+ def write(buf)
84
+ timed(self.write_timeout) do
85
+ send_data buf
86
+ end
87
+ end
88
+
89
+ def receive_data(data)
90
+ trap do
91
+ (@buf) << data
92
+
93
+ if @callback and can_read?(@size)
94
+ callback = @callback
95
+ data = yank(@size)
96
+ @callback = @size = nil
97
+ callback.call(data)
98
+ end
99
+ end
100
+ end
101
+
102
+ def connected?
103
+ !@disconnected
104
+ end
105
+
106
+ def connection_completed
107
+ @disconnected = nil
108
+ succeed
109
+ end
110
+
111
+ def unbind
112
+ if !@disconnected
113
+ @disconnected = 'unbound'
114
+ else
115
+ fail
116
+ end
117
+ end
118
+
119
+ def can_read?(size)
120
+ @buf.size >= @index + size
121
+ end
122
+
123
+ private
124
+
125
+ def create_timer(timeout)
126
+ fiber = Fiber.current
127
+
128
+ EM::Timer.new(timeout) do
129
+ self.close
130
+ @size = nil
131
+ @callback = nil
132
+ @buf = ''
133
+ @index = 0
134
+ @timed_out = true
135
+ fiber.resume false
136
+ end
137
+ end
138
+
139
+ def timed(timeout)
140
+ timer = create_timer(timeout)
141
+ yield.tap do
142
+ timer.cancel
143
+ if @timed_out
144
+ @timed_out = nil
145
+ raise Timeout::Error, "connection to #{@host}:#{@port}: timed out while writing"
146
+ end
147
+ end
148
+ end
149
+
150
+ def yank(len)
151
+ data = @buf.slice(@index, len)
152
+ @index += len
153
+ @index = @buf.size if @index > @buf.size
154
+ if @index >= GARBAGE_BUFFER_SIZE
155
+ @buf = @buf.slice(@index..-1)
156
+ @index = 0
157
+ end
158
+ data
8
159
  end
9
160
  end
10
161
 
@@ -12,7 +163,7 @@ module Dalli
12
163
  class << self
13
164
  def open_with_async(*args)
14
165
  if EM.reactor_running?
15
- KAsyncSocket.new *args
166
+ Dalli::Server::EventMachineConnection.connect *args
16
167
  else
17
168
  open_without_async *args
18
169
  end
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "with_connection"
8
- s.version = "0.1.11"
8
+ s.version = "0.1.12"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Doug Youch"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: with_connection
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.1.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -114,7 +114,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
114
  version: '0'
115
115
  segments:
116
116
  - 0
117
- hash: -1499532644223541582
117
+ hash: 4460793055233630791
118
118
  required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  none: false
120
120
  requirements: