specjour 0.1.12 → 0.1.13

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,4 +1,7 @@
1
1
  # Specjour
2
+
3
+ ## FUCK SETI. Run specs with your spare CPU cycles.
4
+
2
5
  _Distribute your spec suite amongst your LAN via Bonjour._
3
6
 
4
7
  1. Spin up a manager on each machine that can run your specs.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.12
1
+ 0.1.13
data/bin/specjour CHANGED
@@ -23,6 +23,10 @@ optparse = OptionParser.new do |opts|
23
23
  options[:worker_args] = args[0], args[1], args[2]
24
24
  end
25
25
 
26
+ opts.on('--log', TrueClass, 'print debug messages to stdout') do |val|
27
+ Specjour.new_logger Logger::DEBUG
28
+ end
29
+
26
30
  opts.on_tail('-v', '--version', 'Show the version of specjour') do
27
31
  abort Specjour::VERSION
28
32
  end
@@ -1,18 +1,15 @@
1
1
  module Specjour
2
2
  class Connection
3
- MAX_RECONNECTS = 5
4
-
5
3
  include Protocol
6
4
  extend Forwardable
7
5
 
8
6
  attr_reader :uri
9
7
  attr_writer :socket
10
- attr_accessor :reconnection_attempts
11
8
 
12
9
  def_delegators :socket, :flush, :closed?, :close, :gets, :each
13
10
 
14
11
  def self.wrap(established_connection)
15
- host, port = established_connection.peeraddr.values_at(2,1)
12
+ host, port = established_connection.peeraddr.values_at(3,1)
16
13
  connection = new URI::Generic.build(:host => host, :port => port)
17
14
  connection.socket = established_connection
18
15
  connection
@@ -20,23 +17,25 @@ module Specjour
20
17
 
21
18
  def initialize(uri)
22
19
  @uri = uri
23
- @reconnection_attempts = 0
24
20
  end
25
21
 
26
22
  def connect
27
- @socket = TCPSocket.open(uri.host, uri.port)
28
- rescue SystemCallError => error
29
- Kernel.puts "Could not connect to #{uri.to_s}\n#{error.inspect}"
23
+ timeout { connect_socket }
30
24
  end
31
25
 
32
26
  def socket
33
27
  @socket ||= connect
34
28
  end
35
29
 
30
+ def timeout(&block)
31
+ Timeout.timeout(5, &block)
32
+ rescue Timeout::Error
33
+ raise Error, "Connection to dispatcher timed out"
34
+ end
35
+
36
36
  def print(arg)
37
37
  socket.print dump_object(arg)
38
38
  rescue SystemCallError => error
39
- Kernel.p error
40
39
  reconnect
41
40
  retry
42
41
  end
@@ -52,14 +51,16 @@ module Specjour
52
51
 
53
52
  protected
54
53
 
54
+ def connect_socket
55
+ @socket = TCPSocket.open(uri.host, uri.port)
56
+ rescue Errno::ECONNREFUSED => error
57
+ Specjour.logger.debug "Could not connect to #{uri.to_s}\n#{error.inspect}"
58
+ retry
59
+ end
60
+
55
61
  def reconnect
56
- socket.close
57
- if reconnection_attempts < MAX_RECONNECTS
58
- connect
59
- self.reconnection_attempts += 1
60
- else
61
- raise Error, "Lost connection #{MAX_RECONNECTS} times"
62
- end
62
+ socket.close unless socket.closed?
63
+ connect
63
64
  end
64
65
  end
65
66
  end
@@ -40,12 +40,16 @@ module Specjour
40
40
  end
41
41
 
42
42
  def fetch_manager(uri)
43
- manager = DRbObject.new_with_uri(uri.to_s)
44
- if !managers.include?(manager) && manager.available_for?(project_name)
45
- set_up_manager(manager, uri)
46
- managers << manager
47
- self.worker_size += manager.worker_size
43
+ Timeout.timeout(1) do
44
+ manager = DRbObject.new_with_uri(uri.to_s)
45
+ if !managers.include?(manager) && manager.available_for?(project_name)
46
+ set_up_manager(manager, uri)
47
+ managers << manager
48
+ self.worker_size += manager.worker_size
49
+ end
48
50
  end
51
+ rescue Timeout::Error
52
+ Specjour.logger.debug "Couldn't work with manager at #{uri}"
49
53
  end
50
54
 
51
55
  def gather_managers
@@ -53,7 +57,7 @@ module Specjour
53
57
  Signal.trap('INT') { exit }
54
58
  browser = DNSSD::Service.new
55
59
  begin
56
- Timeout.timeout(5) do
60
+ Timeout.timeout(10) do
57
61
  browser.browse '_druby._tcp' do |reply|
58
62
  if reply.flags.add?
59
63
  resolve_reply(reply)
@@ -73,6 +77,10 @@ module Specjour
73
77
  @hostname ||= Socket.gethostname
74
78
  end
75
79
 
80
+ def host_ip
81
+ @host_ip ||= Specjour.ip_from_hostname hostname
82
+ end
83
+
76
84
  def printer
77
85
  @printer ||= begin
78
86
  p = Printer.new
@@ -91,7 +99,8 @@ module Specjour
91
99
 
92
100
  def resolve_reply(reply)
93
101
  DNSSD.resolve!(reply) do |resolved|
94
- uri = URI::Generic.build :scheme => reply.service_name, :host => resolved.target, :port => resolved.port
102
+ resolved_ip = Specjour.ip_from_hostname(resolved.target)
103
+ uri = URI::Generic.build :scheme => reply.service_name, :host => resolved_ip, :port => resolved.port
95
104
  fetch_manager(uri)
96
105
  resolved.service.stop if resolved.service.started?
97
106
  end
@@ -103,7 +112,7 @@ module Specjour
103
112
 
104
113
  def set_up_manager(manager, uri)
105
114
  manager.project_name = project_name
106
- manager.dispatcher_uri = URI::Generic.build :scheme => "specjour", :host => hostname, :port => printer.port
115
+ manager.dispatcher_uri = URI::Generic.build :scheme => "specjour", :host => host_ip, :port => printer.port
107
116
  at_exit { manager.kill_worker_processes }
108
117
  end
109
118
 
@@ -44,7 +44,7 @@ module Specjour
44
44
  def dispatch_workers
45
45
  (1..worker_size).each do |index|
46
46
  worker_pids << fork do
47
- exec("specjour --batch-size #{batch_size} --do-work #{project_path},#{dispatcher_uri},#{index}")
47
+ exec("specjour --batch-size #{batch_size} #{'--log' if Specjour.log?} --do-work #{project_path},#{dispatcher_uri},#{index}")
48
48
  Kernel.exit!
49
49
  end
50
50
  end
data/lib/specjour.rb CHANGED
@@ -9,6 +9,8 @@ autoload :Forwardable, 'forwardable'
9
9
  autoload :GServer, 'gserver'
10
10
  autoload :Timeout, 'timeout'
11
11
  autoload :Benchmark, 'benchmark'
12
+ autoload :Logger, 'logger'
13
+ autoload :Socket, 'socket'
12
14
 
13
15
  module Specjour
14
16
  autoload :Connection, 'specjour/connection'
@@ -21,6 +23,25 @@ module Specjour
21
23
  autoload :RsyncDaemon, 'specjour/rsync_daemon'
22
24
  autoload :Worker, 'specjour/worker'
23
25
 
24
- VERSION = "0.1.12".freeze
26
+ VERSION = "0.1.13".freeze
27
+
25
28
  class Error < StandardError; end
29
+
30
+ def self.logger
31
+ @logger ||= new_logger
32
+ end
33
+
34
+ def self.new_logger(level = Logger::UNKNOWN)
35
+ @logger = Logger.new $stdout
36
+ @logger.level = level
37
+ @logger
38
+ end
39
+
40
+ def self.log?
41
+ logger.level != Logger::UNKNOWN
42
+ end
43
+
44
+ def self.ip_from_hostname(hostname)
45
+ Socket.getaddrinfo(hostname, nil).last.fetch(3)
46
+ end
26
47
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Specjour::Connection do
4
+ require 'stringio'
5
+ describe "#print" do
6
+ context "connection unavailable" do
7
+ let(:connection) do
8
+ Specjour::Connection.new(URI.parse("specjour://me.local:12345"))
9
+ end
10
+
11
+ it "reconnects" do
12
+ socket = mock(:closed? => false, :close => true)
13
+ socket.stub(:print).and_raise(Errno::EPIPE)
14
+ connection.instance_variable_set(:@socket, socket)
15
+ new_socket = mock(:print => true)
16
+ TCPSocket.stub(:open => new_socket)
17
+ connection.print('hi').should be_true
18
+ end
19
+ end
20
+ end
21
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 12
9
- version: 0.1.12
8
+ - 13
9
+ version: 0.1.13
10
10
  platform: ruby
11
11
  authors:
12
12
  - Sandro Turriate
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-04-06 00:00:00 -04:00
17
+ date: 2010-04-14 00:00:00 -04:00
18
18
  default_executable: specjour
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -140,6 +140,7 @@ signing_key:
140
140
  specification_version: 3
141
141
  summary: Distribute your spec suite amongst your LAN via Bonjour.
142
142
  test_files:
143
+ - spec/lib/specjour/connection_spec.rb
143
144
  - spec/lib/specjour/core_ext/array_spec.rb
144
145
  - spec/lib/specjour/worker_spec.rb
145
146
  - spec/spec_helper.rb