flatware 0.4.0 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +40 -42
  3. data/bin/flatware +2 -2
  4. data/lib/flatware.rb +33 -3
  5. data/lib/flatware/broadcaster.rb +20 -3
  6. data/lib/flatware/cli.rb +45 -21
  7. data/lib/flatware/configuration.rb +40 -0
  8. data/lib/flatware/job.rb +22 -0
  9. data/lib/flatware/pid.rb +41 -0
  10. data/lib/flatware/serialized_exception.rb +16 -4
  11. data/lib/flatware/sink.rb +97 -65
  12. data/lib/flatware/sink/client.rb +7 -5
  13. data/lib/flatware/version.rb +3 -1
  14. data/lib/flatware/worker.rb +50 -31
  15. metadata +21 -82
  16. data/lib/flatware-cucumber.rb +0 -1
  17. data/lib/flatware-rspec.rb +0 -1
  18. data/lib/flatware/cucumber.rb +0 -51
  19. data/lib/flatware/cucumber/checkpoint.rb +0 -28
  20. data/lib/flatware/cucumber/cli.rb +0 -22
  21. data/lib/flatware/cucumber/formatter.rb +0 -66
  22. data/lib/flatware/cucumber/formatters/console.rb +0 -48
  23. data/lib/flatware/cucumber/formatters/console/summary.rb +0 -66
  24. data/lib/flatware/cucumber/result.rb +0 -27
  25. data/lib/flatware/cucumber/runtime.rb +0 -36
  26. data/lib/flatware/cucumber/scenario_result.rb +0 -38
  27. data/lib/flatware/cucumber/step_result.rb +0 -30
  28. data/lib/flatware/pids.rb +0 -25
  29. data/lib/flatware/poller.rb +0 -35
  30. data/lib/flatware/processor_info.rb +0 -24
  31. data/lib/flatware/rspec.rb +0 -28
  32. data/lib/flatware/rspec/checkpoint.rb +0 -29
  33. data/lib/flatware/rspec/cli.rb +0 -16
  34. data/lib/flatware/rspec/example_notification.rb +0 -21
  35. data/lib/flatware/rspec/examples_notification.rb +0 -24
  36. data/lib/flatware/rspec/formatter.rb +0 -50
  37. data/lib/flatware/rspec/formatters/console.rb +0 -33
  38. data/lib/flatware/rspec/summary.rb +0 -40
  39. data/lib/flatware/socket.rb +0 -181
data/lib/flatware/sink.rb CHANGED
@@ -1,104 +1,136 @@
1
- require 'flatware'
1
+ require 'drb/drb'
2
+
2
3
  module Flatware
3
4
  module Sink
4
- extend self
5
+ module_function
6
+
7
+ def start_server(**args)
8
+ Server.new(**args).start
9
+ end
5
10
 
6
- def start_server(*args)
7
- Server.new(*args).start
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 :sink, :dispatch, :poller, :workers, :checkpoints, :jobs, :formatter
20
+ attr_reader :checkpoints, :completed_jobs, :formatter, :jobs, :queue, :sink, :workers
12
21
 
13
- def initialize(jobs:, formatter:, dispatch:, sink:, worker_count: 0)
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
- @sink = Flatware.socket(ZMQ::PULL, bind: sink)
17
- @dispatch = Flatware.socket(ZMQ::REP, bind: dispatch)
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
- trap 'INT' do
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
- listen.tap do
36
- Flatware.close
37
- end
35
+ DRb.start_service(sink, self, verbose: Flatware.verbose?)
36
+ DRb.thread.join
37
+ !failures?
38
38
  end
39
39
 
40
- def listen
41
- que = jobs.dup
42
- poller.each do |socket|
43
- message, content = socket.recv
44
-
45
- case message
46
- when :ready
47
- workers << content
48
- job = que.shift
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
- formatter.summarize(checkpoints)
66
- !failures?
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 failures?
72
- checkpoints.any?(&:failures?) || completed_jobs.any?(&:failed?)
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 summarize_remaining
76
- return if remaining_work.empty?
77
- formatter.summarize_remaining remaining_work
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 log(*args)
81
- Flatware.log *args
94
+ def interruped?
95
+ signals = Thread.main[:signals]
96
+ signals && !signals.empty?
82
97
  end
83
98
 
84
- def completed_jobs
85
- @completed_jobs ||= []
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 done?
89
- remaining_work.empty?
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
- jobs.group_by.with_index do |_,i|
99
- i % worker_count
100
- end.values.map do |jobs|
101
- Job.new(jobs.map(&:id), jobs.first.args)
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
@@ -1,15 +1,17 @@
1
- require 'flatware/socket'
1
+ require 'drb/drb'
2
+
2
3
  module Flatware
3
4
  module Sink
4
- extend self
5
+ module_function
6
+
5
7
  attr_accessor :client
6
8
 
7
9
  class Client
8
10
  def initialize(sink_endpoint)
9
- @socket = Flatware.socket ZMQ::PUSH, connect: sink_endpoint
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
- @socket.send message
23
+ @sink.public_send message
22
24
  end
23
25
  end
24
26
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Flatware
2
- VERSION = '0.4.0'
4
+ VERSION = '2.0.0.rc1'
3
5
  end
@@ -1,57 +1,76 @@
1
- require 'flatware/sink/client'
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, dispatch_endpoint, sink_endpoint)
11
+ def initialize(id, runner, sink_endpoint)
7
12
  @id = id
8
13
  @runner = runner
9
- @sink = Sink::Client.new sink_endpoint
10
- @task = Flatware.socket ZMQ::REQ, connect: dispatch_endpoint
14
+ @sink = DRbObject.new_with_uri sink_endpoint
15
+ Flatware::Sink.client = @sink
11
16
  end
12
17
 
13
- def self.spawn(count:, runner:, dispatch:, sink:)
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
- new(i, runner, dispatch, sink).listen
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
- trap 'INT' do
25
- Flatware.close!
26
- @want_to_quit = true
27
- exit(1)
28
- end
29
-
30
- Sink.client = sink
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
- attr_reader :fireable, :task, :sink, :runner
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 report_for_duty
54
- task.send [:ready, id]
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.0
4
+ version: 2.0.0.rc1
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: 2017-01-27 00:00:00.000000000 Z
11
+ date: 2021-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: ffi-rzmq
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
- - !ruby/object:Gem::Dependency
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/cucumber.rb
87
- - lib/flatware/cucumber/checkpoint.rb
88
- - lib/flatware/cucumber/cli.rb
89
- - lib/flatware/cucumber/formatter.rb
90
- - lib/flatware/cucumber/formatters/console.rb
91
- - lib/flatware/cucumber/formatters/console/summary.rb
92
- - lib/flatware/cucumber/result.rb
93
- - lib/flatware/cucumber/runtime.rb
94
- - lib/flatware/cucumber/scenario_result.rb
95
- - lib/flatware/cucumber/step_result.rb
96
- - lib/flatware/pids.rb
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
42
+ - lib/flatware/configuration.rb
43
+ - lib/flatware/job.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: '2.1'
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: '0'
70
+ version: 1.3.1
131
71
  requirements: []
132
- rubyforge_project:
133
- rubygems_version: 2.6.8
134
- signing_key:
72
+ rubygems_version: 3.2.3
73
+ signing_key:
135
74
  specification_version: 4
136
- summary: A distributed cucumber and rspec runner
75
+ summary: A distributed rspec and cucumber runner
137
76
  test_files: []