kosmonaut 0.2.3 → 0.2.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.
data/ChangeLog CHANGED
@@ -1,3 +1,7 @@
1
+ 2012-01-20 Krzysztof Kowalik <chris@nu7hat.ch>
2
+
3
+ * lib/kosmonaut/*.rb: optimized sockets thanks to using raw system timeouts
4
+
1
5
  2012-01-20 Krzysztof Kowalik <chris@nu7hat.ch>
2
6
 
3
7
  * test/test_kosmonaut_worker.rb: shortened test time
@@ -1,16 +1,10 @@
1
1
  require 'json'
2
- require 'uri'
3
- require 'socket'
4
- require 'securerandom'
5
- require 'timeout'
6
2
  require 'thread'
7
3
 
8
4
  module Kosmonaut
9
5
  class Client < Socket
10
- include Kosmonaut
11
-
12
6
  # Maximum number of seconds to wait for the request to being processed.
13
- REQUEST_TIMEOUT = 5
7
+ REQUEST_TIMEOUT = 5.0
14
8
 
15
9
  # Public: The Client constructor. Pre-configures the client instance. See
16
10
  # also the Kosmonaut::Socket#initialize for the details.
@@ -73,21 +67,19 @@ module Kosmonaut
73
67
  def perform_request(payload)
74
68
  @mtx.synchronize {
75
69
  response = []
76
- Timeout.timeout(REQUEST_TIMEOUT) {
77
- s = connect
78
- packet = pack(payload)
79
- log("Client/REQ : #{packet.inspect}")
80
- s.write(packet)
81
- response = recv(s)
82
- s.close
83
- }
70
+ s = connect(REQUEST_TIMEOUT)
71
+ packet = pack(payload)
72
+ Kosmonaut.log("Client/REQ : #{packet.inspect}")
73
+ s.write(packet)
74
+ response = recv(s)
75
+ s.close
84
76
  parse_response(response)
85
77
  }
86
78
  end
87
79
 
88
80
  def parse_response(response)
89
81
  cmd = response[0].to_s
90
- log("Client/RES : #{response.join("\n").inspect}")
82
+ Kosmonaut.log("Client/RES : #{response.join("\n").inspect}")
91
83
  case cmd
92
84
  when "OK"
93
85
  return 0
@@ -1,21 +1,38 @@
1
+ require 'uri'
2
+ require 'socket'
3
+ require 'securerandom'
4
+
1
5
  module Kosmonaut
2
6
  class Socket
3
7
  attr_reader :uri
4
8
 
5
9
  def initialize(url)
6
10
  @uri = URI.parse(url)
11
+ @addr = ::Socket.getaddrinfo(@uri.host, nil)
12
+ end
13
+
14
+ def connect(timeout)
15
+ secs = timeout.to_i
16
+ usecs = ((timeout - secs) * 1_000_000).to_i
17
+ optval = [secs, usecs].pack("l_2")
18
+
19
+ s = ::Socket.new(::Socket.const_get(@addr[0][0]), ::Socket::SOCK_STREAM, 0)
20
+ s.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
21
+ s.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_RCVTIMEO, optval)
22
+ s.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_SNDTIMEO, optval)
23
+ s.connect(::Socket.pack_sockaddr_in(@uri.port, @addr[0][3]))
24
+
7
25
  generate_identity
26
+ return s
8
27
  end
9
28
 
10
29
  protected
11
30
 
12
- def connect
13
- TCPSocket.open(@uri.host, @uri.port)
14
- end
15
-
16
- def pack(payload=[])
17
- payload.unshift("")
18
- payload.unshift(@identity)
31
+ def pack(payload=[], with_identity=true)
32
+ if with_identity
33
+ payload.unshift("")
34
+ payload.unshift(@identity)
35
+ end
19
36
  payload.join("\n") + "\n\r\n\r\n"
20
37
  end
21
38
 
@@ -34,7 +51,7 @@ module Kosmonaut
34
51
  end
35
52
  data
36
53
  end
37
-
54
+
38
55
  private
39
56
 
40
57
  def generate_identity
@@ -2,7 +2,7 @@ module Kosmonaut
2
2
  module Version
3
3
  MAJOR = 0
4
4
  MINOR = 2
5
- PATCH = 3
5
+ PATCH = 4
6
6
 
7
7
  def self.to_s
8
8
  [MAJOR, MINOR, PATCH].join('.')
@@ -3,10 +3,8 @@ require 'thread'
3
3
 
4
4
  module Kosmonaut
5
5
  class Worker < Socket
6
- include Kosmonaut
7
-
8
6
  RECONNECT_DELAY = 1000 # in milliseconds
9
- HEARTBEAT_INTERVAL = 1000 # in milliseconds
7
+ HEARTBEAT_INTERVAL = 500 # in milliseconds
10
8
 
11
9
  def initialize(url)
12
10
  super(url)
@@ -24,20 +22,19 @@ module Kosmonaut
24
22
  while true
25
23
  begin
26
24
  if !alive?
27
- send(@sock, ["QT"]) if @sock
25
+ send(@sock, ["QT"])
28
26
  disconnect
29
27
  break
30
28
  end
31
29
  unless @sock
32
30
  raise Errno::ECONNREFUSED
33
31
  end
34
- msg, cmd = nil, nil
35
- Timeout.timeout(((@heartbeat_ivl * 2).to_f / 1000.0).to_i + 1) {
36
- msg = recv(@sock)
37
- raise Errno::ECONNRESET if @sock.eof? || msg.empty?
38
- log("Worker/RECV : #{msg.join("\n").inspect}")
39
- cmd = msg.shift
40
- }
32
+
33
+ msg = recv(@sock)
34
+ raise Errno::ECONNRESET if @sock.eof? || msg.empty?
35
+ Kosmonaut.log("Worker/RECV : #{msg.join("\n").inspect}")
36
+ cmd = msg.shift
37
+
41
38
  case cmd
42
39
  when "HB"
43
40
  # nothing to do...
@@ -49,11 +46,12 @@ module Kosmonaut
49
46
  when "ER"
50
47
  error_handler(msg.size < 1 ? 597 : msg[0])
51
48
  end
52
- rescue Timeout::Error, Errno::ECONNRESET, Errno::ECONNREFUSED => err
53
- log("Worker/RECONNECT: " + err.to_s)
49
+ rescue Errno::EAGAIN, Errno::ECONNRESET, Errno::ECONNREFUSED, IOError => err
50
+ Kosmonaut.log("Worker/RECONNECT: " + err.to_s)
54
51
  sleep(@reconnect_delay.to_f / 1000.0)
55
52
  reconnect
56
53
  end
54
+ # Send heartbeat if it's time.
57
55
  if Time.now.to_f > @heartbeat_at && @sock
58
56
  send(@sock, ["HB"])
59
57
  @heartbeat_at = Time.now.to_f + (@heartbeat_ivl.to_f / 1000.0)
@@ -75,24 +73,23 @@ module Kosmonaut
75
73
 
76
74
  private
77
75
 
78
- def send(s, payload)
79
- packet = pack(payload.dup)
80
- @sock.write(packet)
81
- log("Worker/SENT : #{(payload.join("\n") + "\n").inspect}")
76
+ def send(s, payload, with_identity=false)
77
+ return unless s
78
+ packet = pack(payload, with_identity)
79
+ s.write(packet)
80
+ Kosmonaut.log("Worker/SENT : #{packet.inspect}")
81
+ rescue Errno::EPIPE
82
82
  end
83
83
 
84
84
  def disconnect
85
- if @sock
86
- @sock.close
87
- @sock = nil
88
- end
85
+ @sock.close if @sock
86
+ rescue IOError
89
87
  end
90
-
88
+
91
89
  def reconnect
92
- disconnect
93
- @sock = connect
94
- send(@sock, ["RD"])
95
- @heartbeat_at = Time.now.to_f + (@heartbeat_ivl.to_f / 1000.0)
90
+ @sock = connect(((@heartbeat_ivl * 2).to_f / 1000.0).to_i + 1)
91
+ send(@sock, ["RD"], true)
92
+ @heartbeat_at = Time.now.to_f + (@heartbeat_ivl.to_f / 1000.0)
96
93
  rescue Errno::ECONNREFUSED
97
94
  end
98
95
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: kosmonaut
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.3
5
+ version: 0.2.4
6
6
  platform: ruby
7
7
  authors:
8
8
  - Krzysztof Kowalik
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2012-01-20 00:00:00 Z
14
+ date: 2012-01-22 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: json
@@ -44,12 +44,12 @@ extensions: []
44
44
  extra_rdoc_files: []
45
45
 
46
46
  files:
47
- - lib/kosmonaut/client.rb
48
- - lib/kosmonaut/errors.rb
47
+ - lib/kosmonaut.rb
49
48
  - lib/kosmonaut/socket.rb
50
- - lib/kosmonaut/version.rb
51
49
  - lib/kosmonaut/worker.rb
52
- - lib/kosmonaut.rb
50
+ - lib/kosmonaut/version.rb
51
+ - lib/kosmonaut/errors.rb
52
+ - lib/kosmonaut/client.rb
53
53
  - test/helper.rb
54
54
  - test/test_kosmonaut_client.rb
55
55
  - test/test_kosmonaut_worker.rb
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
82
82
  requirements: []
83
83
 
84
84
  rubyforge_project:
85
- rubygems_version: 1.8.10
85
+ rubygems_version: 1.8.15
86
86
  signing_key:
87
87
  specification_version: 3
88
88
  summary: Ruby client for the WebRocket backend