flatware 1.0.0 → 2.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +38 -49
- data/bin/flatware +2 -2
- data/lib/flatware.rb +32 -3
- data/lib/flatware/broadcaster.rb +20 -3
- data/lib/flatware/cli.rb +45 -21
- data/lib/flatware/configuration.rb +40 -0
- data/lib/flatware/job.rb +13 -1
- data/lib/flatware/pid.rb +41 -0
- data/lib/flatware/serialized_exception.rb +16 -4
- data/lib/flatware/sink.rb +97 -65
- data/lib/flatware/sink/client.rb +7 -5
- data/lib/flatware/version.rb +3 -1
- data/lib/flatware/worker.rb +50 -31
- metadata +20 -81
- data/lib/flatware-cucumber.rb +0 -1
- data/lib/flatware-rspec.rb +0 -1
- data/lib/flatware/cucumber.rb +0 -50
- data/lib/flatware/cucumber/cli.rb +0 -22
- data/lib/flatware/cucumber/formatter.rb +0 -66
- data/lib/flatware/cucumber/formatters/console.rb +0 -48
- data/lib/flatware/cucumber/formatters/console/summary.rb +0 -65
- data/lib/flatware/cucumber/result.rb +0 -27
- data/lib/flatware/cucumber/runtime.rb +0 -36
- data/lib/flatware/cucumber/scenario_result.rb +0 -38
- data/lib/flatware/cucumber/step_result.rb +0 -30
- data/lib/flatware/pids.rb +0 -25
- data/lib/flatware/poller.rb +0 -35
- data/lib/flatware/processor_info.rb +0 -24
- data/lib/flatware/rspec.rb +0 -28
- data/lib/flatware/rspec/checkpoint.rb +0 -29
- data/lib/flatware/rspec/cli.rb +0 -16
- data/lib/flatware/rspec/example_notification.rb +0 -21
- data/lib/flatware/rspec/examples_notification.rb +0 -24
- data/lib/flatware/rspec/formatter.rb +0 -50
- data/lib/flatware/rspec/formatters/console.rb +0 -33
- data/lib/flatware/rspec/summary.rb +0 -26
- data/lib/flatware/socket.rb +0 -176
data/lib/flatware/sink.rb
CHANGED
@@ -1,104 +1,136 @@
|
|
1
|
-
require '
|
1
|
+
require 'drb/drb'
|
2
|
+
|
2
3
|
module Flatware
|
3
4
|
module Sink
|
4
|
-
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def start_server(**args)
|
8
|
+
Server.new(**args).start
|
9
|
+
end
|
5
10
|
|
6
|
-
def
|
7
|
-
|
11
|
+
def client
|
12
|
+
@client
|
13
|
+
end
|
14
|
+
|
15
|
+
def client=(client)
|
16
|
+
@client = client
|
8
17
|
end
|
9
18
|
|
10
19
|
class Server
|
11
|
-
attr_reader :
|
20
|
+
attr_reader :checkpoints, :completed_jobs, :formatter, :jobs, :queue, :sink, :workers
|
12
21
|
|
13
|
-
def initialize(jobs:, formatter:,
|
22
|
+
def initialize(jobs:, formatter:, sink:, worker_count: 0, **)
|
23
|
+
@checkpoints = []
|
24
|
+
@completed_jobs = []
|
14
25
|
@formatter = formatter
|
15
|
-
@jobs = group_jobs(jobs, worker_count)
|
16
|
-
@
|
17
|
-
@
|
18
|
-
@poller = Poller.new(@sink, @dispatch)
|
26
|
+
@jobs = group_jobs(jobs, worker_count).freeze
|
27
|
+
@queue = @jobs.dup
|
28
|
+
@sink = sink
|
19
29
|
@workers = Set.new(worker_count.times.to_a)
|
20
|
-
@checkpoints = []
|
21
30
|
end
|
22
31
|
|
23
32
|
def start
|
24
|
-
|
25
|
-
puts "Interrupted!"
|
26
|
-
formatter.summarize checkpoints
|
27
|
-
summarize_remaining
|
28
|
-
puts "\n\nCleaning up. Please wait...\n"
|
29
|
-
Flatware.close!
|
30
|
-
Process.waitall
|
31
|
-
puts "thanks."
|
32
|
-
exit 1
|
33
|
-
end
|
33
|
+
trap_interrupt
|
34
34
|
formatter.jobs jobs
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
DRb.start_service(sink, self, verbose: Flatware.verbose?)
|
36
|
+
DRb.thread.join
|
37
|
+
!failures?
|
38
38
|
end
|
39
39
|
|
40
|
-
def
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
if job and not done?
|
50
|
-
dispatch.send job
|
51
|
-
else
|
52
|
-
workers.delete content
|
53
|
-
dispatch.send 'seppuku'
|
54
|
-
end
|
55
|
-
when :checkpoint
|
56
|
-
checkpoints << content
|
57
|
-
when :finished
|
58
|
-
completed_jobs << content
|
59
|
-
formatter.finished content
|
60
|
-
else
|
61
|
-
formatter.send message, content
|
62
|
-
end
|
63
|
-
break if workers.empty? and done?
|
40
|
+
def ready(worker)
|
41
|
+
job = queue.shift
|
42
|
+
if job && !(remaining_work.empty? || interruped?)
|
43
|
+
workers << worker
|
44
|
+
job
|
45
|
+
else
|
46
|
+
workers.delete worker
|
47
|
+
check_finished!
|
48
|
+
Job.sentinel
|
64
49
|
end
|
65
|
-
|
66
|
-
|
50
|
+
end
|
51
|
+
|
52
|
+
def checkpoint(checkpoint)
|
53
|
+
checkpoints << checkpoint
|
54
|
+
end
|
55
|
+
|
56
|
+
def finished(job)
|
57
|
+
completed_jobs << job
|
58
|
+
formatter.finished(job)
|
59
|
+
check_finished!
|
60
|
+
end
|
61
|
+
|
62
|
+
def method_missing(name, *args)
|
63
|
+
super unless formatter.respond_to?(name)
|
64
|
+
Flatware.log(name, *args)
|
65
|
+
formatter.send(name, *args)
|
66
|
+
end
|
67
|
+
|
68
|
+
def respond_to_missing?(name, include_all)
|
69
|
+
formatter.respond_to?(name, include_all)
|
67
70
|
end
|
68
71
|
|
69
72
|
private
|
70
73
|
|
71
|
-
def
|
72
|
-
|
74
|
+
def trap_interrupt
|
75
|
+
Thread.main[:signals] = Queue.new
|
76
|
+
|
77
|
+
Thread.new(&method(:handle_interrupt))
|
78
|
+
|
79
|
+
trap 'INT' do
|
80
|
+
Thread.main[:signals] << :int
|
81
|
+
end
|
73
82
|
end
|
74
83
|
|
75
|
-
def
|
76
|
-
|
77
|
-
|
84
|
+
def handle_interrupt
|
85
|
+
Thread.main[:signals].pop
|
86
|
+
puts 'Interrupted!'
|
87
|
+
summarize_remaining
|
88
|
+
puts "\n\nCleaning up. Please wait...\n"
|
89
|
+
Process.waitall
|
90
|
+
puts 'done.'
|
91
|
+
abort
|
78
92
|
end
|
79
93
|
|
80
|
-
def
|
81
|
-
|
94
|
+
def interruped?
|
95
|
+
signals = Thread.main[:signals]
|
96
|
+
signals && !signals.empty?
|
82
97
|
end
|
83
98
|
|
84
|
-
def
|
85
|
-
|
99
|
+
def check_finished!
|
100
|
+
return unless [workers, remaining_work].all?(&:empty?)
|
101
|
+
|
102
|
+
DRb.stop_service
|
103
|
+
summarize
|
86
104
|
end
|
87
105
|
|
88
|
-
def
|
89
|
-
|
106
|
+
def failures?
|
107
|
+
checkpoints.any?(&:failures?) || completed_jobs.any?(&:failed?)
|
108
|
+
end
|
109
|
+
|
110
|
+
def summarize_remaining
|
111
|
+
summarize
|
112
|
+
return if remaining_work.empty?
|
113
|
+
|
114
|
+
formatter.summarize_remaining remaining_work
|
90
115
|
end
|
91
116
|
|
92
117
|
def remaining_work
|
93
118
|
jobs - completed_jobs
|
94
119
|
end
|
95
120
|
|
121
|
+
def summarize
|
122
|
+
formatter.summarize(checkpoints)
|
123
|
+
end
|
124
|
+
|
96
125
|
def group_jobs(jobs, worker_count)
|
97
126
|
return jobs unless worker_count > 1
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
127
|
+
|
128
|
+
jobs
|
129
|
+
.group_by
|
130
|
+
.with_index { |_, i| i % worker_count }
|
131
|
+
.values
|
132
|
+
.map do |job_group|
|
133
|
+
Job.new(job_group.map(&:id).flatten, jobs.first.args)
|
102
134
|
end
|
103
135
|
end
|
104
136
|
end
|
data/lib/flatware/sink/client.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'drb/drb'
|
2
|
+
|
2
3
|
module Flatware
|
3
4
|
module Sink
|
4
|
-
|
5
|
+
module_function
|
6
|
+
|
5
7
|
attr_accessor :client
|
6
8
|
|
7
9
|
class Client
|
8
10
|
def initialize(sink_endpoint)
|
9
|
-
@
|
11
|
+
@sink = DRbObject.new_with_uri sink_endpoint
|
10
12
|
end
|
11
13
|
|
12
|
-
%w[finished started progress checkpoint].each do |message|
|
14
|
+
%w[ready finished started progress checkpoint].each do |message|
|
13
15
|
define_method message do |content|
|
14
16
|
push [message.to_sym, content]
|
15
17
|
end
|
@@ -18,7 +20,7 @@ module Flatware
|
|
18
20
|
private
|
19
21
|
|
20
22
|
def push(message)
|
21
|
-
@
|
23
|
+
@sink.public_send message
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
data/lib/flatware/version.rb
CHANGED
data/lib/flatware/worker.rb
CHANGED
@@ -1,57 +1,76 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'drb/drb'
|
4
|
+
|
2
5
|
module Flatware
|
6
|
+
require 'flatware/configuration'
|
7
|
+
# executes tests and sends results to the sink
|
3
8
|
class Worker
|
4
|
-
attr_reader :id
|
9
|
+
attr_reader :sink, :runner, :id
|
5
10
|
|
6
|
-
def initialize(id, runner,
|
11
|
+
def initialize(id, runner, sink_endpoint)
|
7
12
|
@id = id
|
8
13
|
@runner = runner
|
9
|
-
@sink =
|
10
|
-
|
14
|
+
@sink = DRbObject.new_with_uri sink_endpoint
|
15
|
+
Flatware::Sink.client = @sink
|
11
16
|
end
|
12
17
|
|
13
|
-
def self.spawn(count:, runner:,
|
18
|
+
def self.spawn(count:, runner:, sink:, **)
|
19
|
+
Flatware.configuration.before_fork.call
|
14
20
|
count.times do |i|
|
15
21
|
fork do
|
16
22
|
$0 = "flatware worker #{i}"
|
17
23
|
ENV['TEST_ENV_NUMBER'] = i.to_s
|
18
|
-
|
24
|
+
Flatware.configuration.after_fork.call(i)
|
25
|
+
new(i, runner, sink).listen
|
19
26
|
end
|
20
27
|
end
|
21
28
|
end
|
22
29
|
|
23
30
|
def listen
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
report_for_duty
|
32
|
-
loop do
|
33
|
-
job = task.recv
|
34
|
-
break if job == 'seppuku' or @want_to_quit
|
35
|
-
job.worker = id
|
36
|
-
sink.started job
|
37
|
-
begin
|
38
|
-
runner.run job.id, job.args
|
39
|
-
rescue => e
|
40
|
-
Flatware.log e
|
41
|
-
job.failed = true
|
31
|
+
retrying(times: 10, wait: 0.1) do
|
32
|
+
job = sink.ready id
|
33
|
+
until want_to_quit? || job.sentinel?
|
34
|
+
job.worker = id
|
35
|
+
sink.started job
|
36
|
+
run job
|
37
|
+
job = sink.ready id
|
42
38
|
end
|
43
|
-
sink.finished job
|
44
|
-
report_for_duty
|
45
39
|
end
|
46
|
-
Flatware.close unless @want_to_quit
|
47
40
|
end
|
48
41
|
|
49
42
|
private
|
50
43
|
|
51
|
-
|
44
|
+
def run(job)
|
45
|
+
runner.run job.id, job.args
|
46
|
+
sink.finished job
|
47
|
+
rescue Interrupt
|
48
|
+
want_to_quit!
|
49
|
+
rescue StandardError => e
|
50
|
+
Flatware.log e
|
51
|
+
job.failed!
|
52
|
+
sink.finished job
|
53
|
+
end
|
52
54
|
|
53
|
-
def
|
54
|
-
|
55
|
+
def want_to_quit!
|
56
|
+
@want_to_quit = true
|
57
|
+
end
|
58
|
+
|
59
|
+
def want_to_quit?
|
60
|
+
@want_to_quit == true
|
61
|
+
end
|
62
|
+
|
63
|
+
def retrying(times:, wait:)
|
64
|
+
tries = 0
|
65
|
+
begin
|
66
|
+
yield unless want_to_quit?
|
67
|
+
rescue DRb::DRbConnError => e
|
68
|
+
raise if (tries += 1) >= times
|
69
|
+
|
70
|
+
sleep wait
|
71
|
+
Flatware.log('retrying', e.message)
|
72
|
+
retry
|
73
|
+
end
|
55
74
|
end
|
56
75
|
end
|
57
76
|
end
|
metadata
CHANGED
@@ -1,72 +1,30 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flatware
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brian Dunn
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: thor
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "<"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "<"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.0'
|
27
|
-
|
28
|
-
name: thor
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0.13'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0.13'
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: aruba
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0.14'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0.14'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 10.1.0
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - "~>"
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: 10.1.0
|
69
|
-
description: A distributed cucumber and rspec runner
|
27
|
+
description: A distributed rspec and cucumber runner
|
70
28
|
email: brian@hashrocket.com
|
71
29
|
executables:
|
72
30
|
- flatware
|
@@ -78,60 +36,41 @@ files:
|
|
78
36
|
- LICENSE.txt
|
79
37
|
- README.md
|
80
38
|
- bin/flatware
|
81
|
-
- lib/flatware-cucumber.rb
|
82
|
-
- lib/flatware-rspec.rb
|
83
39
|
- lib/flatware.rb
|
84
40
|
- lib/flatware/broadcaster.rb
|
85
41
|
- lib/flatware/cli.rb
|
86
|
-
- lib/flatware/
|
87
|
-
- lib/flatware/cucumber/cli.rb
|
88
|
-
- lib/flatware/cucumber/formatter.rb
|
89
|
-
- lib/flatware/cucumber/formatters/console.rb
|
90
|
-
- lib/flatware/cucumber/formatters/console/summary.rb
|
91
|
-
- lib/flatware/cucumber/result.rb
|
92
|
-
- lib/flatware/cucumber/runtime.rb
|
93
|
-
- lib/flatware/cucumber/scenario_result.rb
|
94
|
-
- lib/flatware/cucumber/step_result.rb
|
42
|
+
- lib/flatware/configuration.rb
|
95
43
|
- lib/flatware/job.rb
|
96
|
-
- lib/flatware/
|
97
|
-
- lib/flatware/poller.rb
|
98
|
-
- lib/flatware/processor_info.rb
|
99
|
-
- lib/flatware/rspec.rb
|
100
|
-
- lib/flatware/rspec/checkpoint.rb
|
101
|
-
- lib/flatware/rspec/cli.rb
|
102
|
-
- lib/flatware/rspec/example_notification.rb
|
103
|
-
- lib/flatware/rspec/examples_notification.rb
|
104
|
-
- lib/flatware/rspec/formatter.rb
|
105
|
-
- lib/flatware/rspec/formatters/console.rb
|
106
|
-
- lib/flatware/rspec/summary.rb
|
44
|
+
- lib/flatware/pid.rb
|
107
45
|
- lib/flatware/serialized_exception.rb
|
108
46
|
- lib/flatware/sink.rb
|
109
47
|
- lib/flatware/sink/client.rb
|
110
|
-
- lib/flatware/socket.rb
|
111
48
|
- lib/flatware/version.rb
|
112
49
|
- lib/flatware/worker.rb
|
113
50
|
homepage: http://github.com/briandunn/flatware
|
114
51
|
licenses:
|
115
52
|
- MIT
|
116
53
|
metadata: {}
|
117
|
-
post_install_message:
|
54
|
+
post_install_message:
|
118
55
|
rdoc_options: []
|
119
56
|
require_paths:
|
120
57
|
- lib
|
121
58
|
required_ruby_version: !ruby/object:Gem::Requirement
|
122
59
|
requirements:
|
123
|
-
- - "
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '2.6'
|
63
|
+
- - "<"
|
124
64
|
- !ruby/object:Gem::Version
|
125
|
-
version: '
|
65
|
+
version: '3.1'
|
126
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
67
|
requirements:
|
128
|
-
- - "
|
68
|
+
- - ">"
|
129
69
|
- !ruby/object:Gem::Version
|
130
|
-
version:
|
70
|
+
version: 1.3.1
|
131
71
|
requirements: []
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
72
|
+
rubygems_version: 3.2.3
|
73
|
+
signing_key:
|
135
74
|
specification_version: 4
|
136
|
-
summary: A distributed
|
75
|
+
summary: A distributed rspec and cucumber runner
|
137
76
|
test_files: []
|