flatware 0.4.1 → 2.0.0.rc2
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.
- checksums.yaml +5 -5
- data/README.md +38 -47
- 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: 0.
|
4
|
+
version: 2.0.0.rc2
|
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-02 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: []
|