arya-pandemic 0.4.1 → 0.4.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +1 -0
- data/README.markdown +4 -0
- data/Rakefile +1 -1
- data/lib/pandemic.rb +5 -10
- data/lib/pandemic/requests_per_second.rb +31 -0
- data/lib/pandemic/server_side/server.rb +21 -4
- data/pandemic.gemspec +4 -4
- data/test/server_test.rb +27 -0
- metadata +4 -2
data/Manifest
CHANGED
@@ -10,6 +10,7 @@ lib/pandemic/client_side/connection_proxy.rb
|
|
10
10
|
lib/pandemic/client_side/pandemize.rb
|
11
11
|
lib/pandemic/connection_pool.rb
|
12
12
|
lib/pandemic/mutex_counter.rb
|
13
|
+
lib/pandemic/requests_per_second.rb
|
13
14
|
lib/pandemic/server_side/client.rb
|
14
15
|
lib/pandemic/server_side/config.rb
|
15
16
|
lib/pandemic/server_side/handler.rb
|
data/README.markdown
CHANGED
@@ -119,6 +119,10 @@ The servers are going to try to bind to localhost:4000 and localhost:4001 so mak
|
|
119
119
|
By default, the handler runs in the same Ruby process as Pandemic. By setting the fork\_for\_processor to true in pandemic\_server.yml, you can have Pandemic fork to new processes to run the process method. This is particularly useful when your process method goes to MySQL which locks the entire process until MySQL returns.
|
120
120
|
|
121
121
|
## Change History
|
122
|
+
**Version 0.4.2**
|
123
|
+
|
124
|
+
* Log file and log level now specify-able as hash attributes to the _epidemic!_ method.
|
125
|
+
|
122
126
|
**Version 0.3.1**
|
123
127
|
|
124
128
|
* Changed map to partition to more accurately reflect what it does. This breaks backwards compatibility, but all you have to do is rename your method.
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('pandemic', '0.4.
|
5
|
+
Echoe.new('pandemic', '0.4.3') do |p|
|
6
6
|
p.description = "A framework for distributing work for real-time services and offline tasks."
|
7
7
|
p.url = "https://github.com/arya/pandemic/"
|
8
8
|
p.author = "Arya Asemanfar"
|
data/lib/pandemic.rb
CHANGED
@@ -10,6 +10,7 @@ require 'logger'
|
|
10
10
|
require 'pandemic/util'
|
11
11
|
require 'pandemic/connection_pool'
|
12
12
|
require 'pandemic/mutex_counter'
|
13
|
+
require 'pandemic/requests_per_second'
|
13
14
|
|
14
15
|
require 'pandemic/server_side/config'
|
15
16
|
require 'pandemic/server_side/client'
|
@@ -25,22 +26,16 @@ require 'pandemic/client_side/connection'
|
|
25
26
|
require 'pandemic/client_side/connection_proxy'
|
26
27
|
require 'pandemic/client_side/pandemize'
|
27
28
|
|
28
|
-
# TODO:
|
29
|
-
# - tests
|
30
|
-
# - IO timeouts/robustness
|
31
|
-
# - documentation
|
32
|
-
# - PING/PONG?
|
33
|
-
|
34
29
|
TCP_NO_DELAY_AVAILABLE =
|
35
30
|
RUBY_VERSION < '1.9' ? Socket.constants.include?('TCP_NODELAY') : Socket.constants.include?(:TCP_NODELAY)
|
36
31
|
|
37
|
-
def epidemic!(
|
32
|
+
def epidemic!(options = {})
|
38
33
|
if $pandemic_logger.nil?
|
39
|
-
$pandemic_logger = Logger.new("pandemic.log")
|
40
|
-
$pandemic_logger.level = Logger::INFO
|
34
|
+
$pandemic_logger = Logger.new(options[:log_file] || "pandemic.log")
|
35
|
+
$pandemic_logger.level = options[:log_level] || Logger::INFO
|
41
36
|
$pandemic_logger.datetime_format = "%Y-%m-%d %H:%M:%S "
|
42
37
|
end
|
43
|
-
Pandemic::ServerSide::Server.boot(bind_to)
|
38
|
+
Pandemic::ServerSide::Server.boot(options[:bind_to])
|
44
39
|
end
|
45
40
|
|
46
41
|
::Pandemize = Pandemic::ClientSide::Pandemize
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Pandemic
|
2
|
+
class RequestsPerSecond
|
3
|
+
def initialize(sample_size = 10)
|
4
|
+
@hits = Array.new(sample_size + 2)
|
5
|
+
@last_hit_at = nil
|
6
|
+
end
|
7
|
+
|
8
|
+
def hit(now = Time.now.to_i)
|
9
|
+
key = now % @hits.size
|
10
|
+
if @hits[key].nil? || @hits[key][0] != now
|
11
|
+
@hits[key] = [now, 0]
|
12
|
+
end
|
13
|
+
@hits[key][1] += 1
|
14
|
+
@last_hit_at = now
|
15
|
+
end
|
16
|
+
|
17
|
+
def rps(now = Time.now.to_i)
|
18
|
+
return 0 if @last_hit_at.nil?
|
19
|
+
entries_to_go_back = @hits.size - (now - @last_hit_at) - 2
|
20
|
+
return 0 if entries_to_go_back <= 0
|
21
|
+
sum = 0
|
22
|
+
entries_to_go_back.times do |i|
|
23
|
+
now -= 1
|
24
|
+
if @hits[now % @hits.size] && @hits[now % @hits.size][0] == now
|
25
|
+
sum += @hits[now % @hits.size][1]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
return sum.to_f / (@hits.size - 2)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -33,8 +33,9 @@ module Pandemic
|
|
33
33
|
@clients_mutex = Mutex.new
|
34
34
|
@num_jobs_processed = MutexCounter.new
|
35
35
|
@num_jobs_entered = MutexCounter.new
|
36
|
+
@requests_per_second = RequestsPerSecond.new(10)
|
36
37
|
|
37
|
-
@peers = {}
|
38
|
+
@peers = with_mutex({})
|
38
39
|
@servers = Config.servers
|
39
40
|
@servers.each do |peer|
|
40
41
|
next if peer == bind_to # not a peer, it's itself
|
@@ -64,7 +65,7 @@ module Pandemic
|
|
64
65
|
debug("Listening")
|
65
66
|
conn = @listener.accept
|
66
67
|
Thread.new(conn) { |c| handle_connection(c) }
|
67
|
-
rescue Errno::ECONNABORTED, Errno::EINTR
|
68
|
+
rescue Errno::ECONNABORTED, Errno::EINTR # TODO: what else can wrong here? this should be more robust.
|
68
69
|
debug("Connection accepted aborted")
|
69
70
|
conn.close if conn && !conn.closed?
|
70
71
|
end
|
@@ -96,8 +97,17 @@ module Pandemic
|
|
96
97
|
debug("Recognized as peer")
|
97
98
|
host, port = host_port($1)
|
98
99
|
matching_peer = @peers.values.detect { |peer| [peer.host, peer.port] == [host, port] }
|
99
|
-
|
100
|
-
|
100
|
+
if matching_peer
|
101
|
+
debug("Found matching peer")
|
102
|
+
else
|
103
|
+
debug("Didn't find matching peer, adding it")
|
104
|
+
matching_peer = @peers.synchronize do
|
105
|
+
hostport = "#{host}:#{port}"
|
106
|
+
@servers.push(hostport) unless @servers.include?(hostport)
|
107
|
+
@peers[hostport] ||= Peer.new(hostport, self)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
matching_peer.add_incoming_connection(connection)
|
101
111
|
elsif identification =~ /^CLIENT$/
|
102
112
|
debug("Recognized as client")
|
103
113
|
@clients_mutex.synchronize do
|
@@ -139,6 +149,8 @@ module Pandemic
|
|
139
149
|
end
|
140
150
|
end
|
141
151
|
|
152
|
+
@requests_per_second.hit
|
153
|
+
|
142
154
|
debug("Waiting for responses")
|
143
155
|
request.wait_for_responses
|
144
156
|
|
@@ -202,6 +214,8 @@ module Pandemic
|
|
202
214
|
str << "Late Responses: #{stats[:late_responses]}"
|
203
215
|
str << "Total Jobs Processed: #{stats[:total_jobs_processed]}"
|
204
216
|
str << "Pending Jobs: #{stats[:jobs_pending]}"
|
217
|
+
str << "Requests per Second (10 sec): #{"%.1f" % stats[:rps_10]}"
|
218
|
+
str << "Requests per Second (lifetime): #{"%.1f" % stats[:rps_lifetime]}"
|
205
219
|
connection.puts(str.join("\n"))
|
206
220
|
end while (s = connection.gets) && (s.strip == "stats" || s.strip == "")
|
207
221
|
connection.close if connection && !connection.closed?
|
@@ -243,8 +257,11 @@ module Pandemic
|
|
243
257
|
pending + (client.received_requests - client.responded_requests.to_i)
|
244
258
|
end
|
245
259
|
end
|
260
|
+
results[:rps_10] = @requests_per_second.rps
|
246
261
|
|
247
262
|
results[:uptime] = Time.now - @running_since
|
263
|
+
results[:rps_lifetime] = results[:num_requests] / results[:uptime]
|
264
|
+
|
248
265
|
results
|
249
266
|
end
|
250
267
|
|
data/pandemic.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{pandemic}
|
5
|
-
s.version = "0.4.
|
5
|
+
s.version = "0.4.3"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Arya Asemanfar"]
|
9
|
-
s.date = %q{2009-07-
|
9
|
+
s.date = %q{2009-07-20}
|
10
10
|
s.description = %q{A framework for distributing work for real-time services and offline tasks.}
|
11
11
|
s.email = %q{aryaasemanfar@gmail.com}
|
12
|
-
s.extra_rdoc_files = ["lib/pandemic/client_side/cluster_connection.rb", "lib/pandemic/client_side/config.rb", "lib/pandemic/client_side/connection.rb", "lib/pandemic/client_side/connection_proxy.rb", "lib/pandemic/client_side/pandemize.rb", "lib/pandemic/connection_pool.rb", "lib/pandemic/mutex_counter.rb", "lib/pandemic/server_side/client.rb", "lib/pandemic/server_side/config.rb", "lib/pandemic/server_side/handler.rb", "lib/pandemic/server_side/peer.rb", "lib/pandemic/server_side/processor.rb", "lib/pandemic/server_side/request.rb", "lib/pandemic/server_side/server.rb", "lib/pandemic/util.rb", "lib/pandemic.rb", "README.markdown"]
|
13
|
-
s.files = ["examples/client/client.rb", "examples/client/constitution.txt", "examples/client/pandemic_client.yml", "examples/server/pandemic_server.yml", "examples/server/word_count_server.rb", "lib/pandemic/client_side/cluster_connection.rb", "lib/pandemic/client_side/config.rb", "lib/pandemic/client_side/connection.rb", "lib/pandemic/client_side/connection_proxy.rb", "lib/pandemic/client_side/pandemize.rb", "lib/pandemic/connection_pool.rb", "lib/pandemic/mutex_counter.rb", "lib/pandemic/server_side/client.rb", "lib/pandemic/server_side/config.rb", "lib/pandemic/server_side/handler.rb", "lib/pandemic/server_side/peer.rb", "lib/pandemic/server_side/processor.rb", "lib/pandemic/server_side/request.rb", "lib/pandemic/server_side/server.rb", "lib/pandemic/util.rb", "lib/pandemic.rb", "Manifest", "MIT-LICENSE", "pandemic.gemspec", "Rakefile", "README.markdown", "test/client_test.rb", "test/connection_pool_test.rb", "test/functional_test.rb", "test/handler_test.rb", "test/mutex_counter_test.rb", "test/peer_test.rb", "test/processor_test.rb", "test/server_test.rb", "test/test_helper.rb", "test/util_test.rb"]
|
12
|
+
s.extra_rdoc_files = ["lib/pandemic/client_side/cluster_connection.rb", "lib/pandemic/client_side/config.rb", "lib/pandemic/client_side/connection.rb", "lib/pandemic/client_side/connection_proxy.rb", "lib/pandemic/client_side/pandemize.rb", "lib/pandemic/connection_pool.rb", "lib/pandemic/mutex_counter.rb", "lib/pandemic/requests_per_second.rb", "lib/pandemic/server_side/client.rb", "lib/pandemic/server_side/config.rb", "lib/pandemic/server_side/handler.rb", "lib/pandemic/server_side/peer.rb", "lib/pandemic/server_side/processor.rb", "lib/pandemic/server_side/request.rb", "lib/pandemic/server_side/server.rb", "lib/pandemic/util.rb", "lib/pandemic.rb", "README.markdown"]
|
13
|
+
s.files = ["examples/client/client.rb", "examples/client/constitution.txt", "examples/client/pandemic_client.yml", "examples/server/pandemic_server.yml", "examples/server/word_count_server.rb", "lib/pandemic/client_side/cluster_connection.rb", "lib/pandemic/client_side/config.rb", "lib/pandemic/client_side/connection.rb", "lib/pandemic/client_side/connection_proxy.rb", "lib/pandemic/client_side/pandemize.rb", "lib/pandemic/connection_pool.rb", "lib/pandemic/mutex_counter.rb", "lib/pandemic/requests_per_second.rb", "lib/pandemic/server_side/client.rb", "lib/pandemic/server_side/config.rb", "lib/pandemic/server_side/handler.rb", "lib/pandemic/server_side/peer.rb", "lib/pandemic/server_side/processor.rb", "lib/pandemic/server_side/request.rb", "lib/pandemic/server_side/server.rb", "lib/pandemic/util.rb", "lib/pandemic.rb", "Manifest", "MIT-LICENSE", "pandemic.gemspec", "Rakefile", "README.markdown", "test/client_test.rb", "test/connection_pool_test.rb", "test/functional_test.rb", "test/handler_test.rb", "test/mutex_counter_test.rb", "test/peer_test.rb", "test/processor_test.rb", "test/server_test.rb", "test/test_helper.rb", "test/util_test.rb"]
|
14
14
|
s.homepage = %q{https://github.com/arya/pandemic/}
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Pandemic", "--main", "README.markdown"]
|
16
16
|
s.require_paths = ["lib"]
|
data/test/server_test.rb
CHANGED
@@ -3,6 +3,33 @@ require 'test_helper'
|
|
3
3
|
class ServerTest < Test::Unit::TestCase
|
4
4
|
include TestHelper
|
5
5
|
|
6
|
+
context "without a peer list" do
|
7
|
+
setup do
|
8
|
+
Pandemic::ServerSide::Config.expects(:servers).returns(["localhost:4000"])
|
9
|
+
@server = Pandemic::ServerSide::Server.new("localhost:4000")
|
10
|
+
end
|
11
|
+
|
12
|
+
should "create a peer connection when a unknown peer tries to connect" do
|
13
|
+
ignore_threads = Thread.list
|
14
|
+
@tcpserver = mock()
|
15
|
+
TCPServer.expects(:new).with("localhost", 4000).returns(@tcpserver)
|
16
|
+
|
17
|
+
@conn = mock(:peeraddr => ['','','',''])
|
18
|
+
@tcpserver.expects(:accept).twice.returns(@conn).then.raises(Pandemic::ServerSide::Server::StopServer)
|
19
|
+
peer = mock()
|
20
|
+
@conn.expects(:setsockopt).with(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1)
|
21
|
+
|
22
|
+
@conn.expects(:gets).returns("SERVER localhost:4001\n")
|
23
|
+
Pandemic::ServerSide::Peer.expects(:new).with("localhost:4001", is_a(Pandemic::ServerSide::Server)).returns(peer)
|
24
|
+
@tcpserver.expects(:close)
|
25
|
+
peer.stubs(:disconnect) # the StopServer signal could be called before the peer is added. race case not important for this test
|
26
|
+
|
27
|
+
@server.handler = mock(:new)
|
28
|
+
@server.start
|
29
|
+
wait_for_threads(ignore_threads)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
6
33
|
should "initialize peers" do
|
7
34
|
Pandemic::ServerSide::Config.expects(:servers).returns(["localhost:4000", "localhost:4001"])
|
8
35
|
Pandemic::ServerSide::Peer.expects(:new).with("localhost:4001", is_a(Pandemic::ServerSide::Server))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arya-pandemic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arya Asemanfar
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-20 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -46,6 +46,7 @@ extra_rdoc_files:
|
|
46
46
|
- lib/pandemic/client_side/pandemize.rb
|
47
47
|
- lib/pandemic/connection_pool.rb
|
48
48
|
- lib/pandemic/mutex_counter.rb
|
49
|
+
- lib/pandemic/requests_per_second.rb
|
49
50
|
- lib/pandemic/server_side/client.rb
|
50
51
|
- lib/pandemic/server_side/config.rb
|
51
52
|
- lib/pandemic/server_side/handler.rb
|
@@ -69,6 +70,7 @@ files:
|
|
69
70
|
- lib/pandemic/client_side/pandemize.rb
|
70
71
|
- lib/pandemic/connection_pool.rb
|
71
72
|
- lib/pandemic/mutex_counter.rb
|
73
|
+
- lib/pandemic/requests_per_second.rb
|
72
74
|
- lib/pandemic/server_side/client.rb
|
73
75
|
- lib/pandemic/server_side/config.rb
|
74
76
|
- lib/pandemic/server_side/handler.rb
|