specwrk 0.4.11 → 0.5.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e85bdff31c7f1312b12a9a823200a5da5b36653433496556cc1bce274a3dc90a
4
- data.tar.gz: fa73aebb69753d7b528d333f2fca589e0e5525bd12b71e4c5b7815df0932b9a1
3
+ metadata.gz: 331e0982599a516c3c862c4a5c33a825c71256f5f95e6d1656c0ad410541df06
4
+ data.tar.gz: c7d93bf3add6e6de08cad22f8036ef89b01752b0e6dfe42615035d9e301ecff5
5
5
  SHA512:
6
- metadata.gz: 9467744c0cd676bdeb312b3f1deb4190113601cb01bb9ce939acdfa1c6170897904f3125b43c90dde536459ed56b2623be132bfeed84725c1f6b098ea65ae6a9
7
- data.tar.gz: f8cd7800b9f117567c1aa53404f2ca7f9a99a907c4b46c1c05da34d7534a2743c68960c50ffd9555de82430f582cb6a042a70579e4a8a44f53dea136f72cd8ae
6
+ metadata.gz: 9daa901f8a7b7f453079f766d09e47fb621cf85e1cdb6111303e1f8b17cc3091312b2128ca141328f1c8a28216151b991f431cbb4550445ce137349dcb30f3c5
7
+ data.tar.gz: f0ae841735759d62e9ad6607065ca7bc8747a9d85e8906dea19019af7c63183df26b82cce51bc2a8c453cf4e1bb7d3d0b0c900c917cf689730cdac6028efaae5
data/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## v0.4.11
4
+
5
+ - Move logic out of CLI methods ([#64](https://github.com/danielwestendorf/specwrk/issues/64)) by @danielwestendorf
6
+ - Add thruster in front of puma ([#65](https://github.com/danielwestendorf/specwrk/issues/65)) by @danielwestendorf
7
+ - Revise heartbeats logic ([#66](https://github.com/danielwestendorf/specwrk/issues/66)) by @danielwestendorf
8
+
9
+ ## v0.4.9
10
+
11
+ - Remove single-run env var (it was not what I wanted) by @danielwestendorf
12
+
13
+ ## v0.4.8
14
+
15
+ - Fix `config.ru` by @danielwestendorf
16
+
17
+ ## v0.4.7
18
+
19
+ - Switch to Puma for the Docker image (#59) by @danielwestendorf
20
+
21
+ ## v0.4.6
22
+
23
+ - Nil env var that will prevent start command from completing ([#56](https://github.com/danielwestendorf/specwrk/issues/56)) by @danielwestendorf
24
+ - Better handling of seed failing ([#57](https://github.com/danielwestendorf/specwrk/issues/57)) by @danielwestendorf
25
+ - Silence health logging ([#58](https://github.com/danielwestendorf/specwrk/issues/58)) by @danielwestendorf
26
+ - Add missing CCI caching of `report.json` ([#55](https://github.com/danielwestendorf/specwrk/issues/55)) by @danielwestendorf
27
+ - Add CircleCI examples ([#50](https://github.com/danielwestendorf/specwrk/issues/50)) by @danielwestendorf
28
+ - Better GHA Examples ([#49](https://github.com/danielwestendorf/specwrk/issues/49)) by @danielwestendorf
29
+ - Skip key lookup and rely on the result of `Hash#delete` instead by @danielwestendorf
30
+
3
31
  ## v0.4.5
4
32
 
5
33
  - Set ENV var when generating seed examples [#47](https://github.com/danielwestendorf/specwrk/issues/47). by @danielwestendorf
data/README.md CHANGED
@@ -129,7 +129,7 @@ Description:
129
129
  Start one or more worker processes
130
130
 
131
131
  Options:
132
- --id=VALUE # The identifier for this worker. Default specwrk-worker(-COUNT_INDEX), default: "specwrk-worker"
132
+ --id=VALUE # The identifier for this worker. Overrides SPECWRK_ID. If none provided one in the format of specwrk-worker-8_RAND_CHARS-COUNT_INDEX will be used
133
133
  --count=VALUE, -c VALUE # The number of worker processes you want to start, default: 1
134
134
  --output=VALUE, -o VALUE # Directory where worker output is stored. Overrides SPECWRK_OUT, default: ".specwrk/"
135
135
  --seed-waits=VALUE, -w VALUE # Number of times the worker will wait for examples to be seeded to the server. 1sec between attempts. Overrides SPECWRK_SEED_WAITS, default: "10"
data/lib/specwrk/cli.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "pathname"
4
+ require "securerandom"
4
5
 
5
6
  require "dry/cli"
6
7
 
@@ -33,14 +34,15 @@ module Specwrk
33
34
  extend Hookable
34
35
 
35
36
  on_included do |base|
36
- base.unique_option :id, type: :string, default: "specwrk-worker", desc: "The identifier for this worker. Default specwrk-worker(-COUNT_INDEX)"
37
+ base.unique_option :id, type: :string, desc: "The identifier for this worker. Overrides SPECWRK_ID. If none provided one in the format of specwrk-worker-8_RAND_CHARS-COUNT_INDEX will be used"
37
38
  base.unique_option :count, type: :integer, default: 1, aliases: ["-c"], desc: "The number of worker processes you want to start"
38
39
  base.unique_option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored. Overrides SPECWRK_OUT"
39
40
  base.unique_option :seed_waits, type: :integer, default: ENV.fetch("SPECWRK_SEED_WAITS", "10"), aliases: ["-w"], desc: "Number of times the worker will wait for examples to be seeded to the server. 1sec between attempts. Overrides SPECWRK_SEED_WAITS"
40
41
  end
41
42
 
42
- on_setup do |id:, count:, output:, seed_waits:, **|
43
- ENV["SPECWRK_ID"] = id
43
+ on_setup do |count:, output:, seed_waits:, id: "specwrk-worker-#{SecureRandom.uuid[0, 8]}", **|
44
+ ENV["SPECWRK_ID"] ||= id # Unique default. Don't override the ENV value here
45
+
44
46
  ENV["SPECWRK_COUNT"] = count.to_s
45
47
  ENV["SPECWRK_SEED_WAITS"] = seed_waits.to_s
46
48
  ENV["SPECWRK_OUT"] = Pathname.new(output).expand_path(Dir.pwd).to_s
@@ -115,6 +117,8 @@ module Specwrk
115
117
 
116
118
  Client.wait_for_server!
117
119
  Client.new.seed(examples)
120
+ file_count = examples.group_by { |e| e[:file_path] }.keys.size
121
+ puts "🌱 Seeded #{examples.size} examples across #{file_count} files"
118
122
  rescue Errno::ECONNREFUSED
119
123
  puts "Server at #{ENV.fetch("SPECWRK_SRV_URI", "http://localhost:5138")} is refusing connections, exiting...#{ENV["SPECWRK_FLUSH_DELIMINATOR"]}"
120
124
  exit 1
@@ -150,7 +150,9 @@ module Specwrk
150
150
 
151
151
  def default_headers
152
152
  @default_headers ||= {}.tap do |h|
153
+ h["User-Agent"] = "Specwrk/#{VERSION}"
153
154
  h["Authorization"] = "Bearer #{ENV["SPECWRK_SRV_KEY"]}" if ENV["SPECWRK_SRV_KEY"]
155
+ h["X-Specwrk-Id"] = ENV.fetch("SPECWRK_ID", "specwrk-client")
154
156
  h["X-Specwrk-Run"] = ENV["SPECWRK_RUN"] if ENV["SPECWRK_RUN"]
155
157
  h["Content-Type"] = "application/json"
156
158
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specwrk
4
- VERSION = "0.4.11"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -13,6 +13,7 @@ rescue LoadError
13
13
  require "rack/handler/webrick"
14
14
  end
15
15
 
16
+ require "specwrk/web"
16
17
  require "specwrk/web/logger"
17
18
  require "specwrk/web/auth"
18
19
  require "specwrk/web/endpoints"
@@ -20,6 +21,8 @@ require "specwrk/web/endpoints"
20
21
  module Specwrk
21
22
  class Web
22
23
  class App
24
+ REAP_INTERVAL = 330 # HTTP connection timeout + some buffer
25
+
23
26
  class << self
24
27
  def run!
25
28
  Process.setproctitle "specwrk-server"
@@ -73,6 +76,10 @@ module Specwrk
73
76
  end
74
77
  end
75
78
 
79
+ def initialize
80
+ @reaper_thread = Thread.new { reaper } unless ENV["SPECWRK_SRV_SINGLE_RUN"]
81
+ end
82
+
76
83
  def call(env)
77
84
  env[:request] ||= Rack::Request.new(env)
78
85
 
@@ -101,6 +108,26 @@ module Specwrk
101
108
  Endpoints::NotFound
102
109
  end
103
110
  end
111
+
112
+ def reaper
113
+ until Specwrk.force_quit
114
+ sleep REAP_INTERVAL
115
+
116
+ reap
117
+ end
118
+ end
119
+
120
+ def reap
121
+ Web::WORKERS.each do |run, workers|
122
+ most_recent_last_seen_at = workers.map { |id, worker| worker[:last_seen_at] }.max
123
+ next unless most_recent_last_seen_at
124
+
125
+ # Don't consider runs which aren't at least REAP_INTERVAL sec stale
126
+ if most_recent_last_seen_at < Time.now - REAP_INTERVAL
127
+ Web.clear_run_queues(run)
128
+ end
129
+ end
130
+ end
104
131
  end
105
132
  end
106
133
  end
@@ -8,6 +8,9 @@ module Specwrk
8
8
  class Base
9
9
  def initialize(request)
10
10
  @request = request
11
+
12
+ worker[:first_seen_at] ||= Time.now
13
+ worker[:last_seen_at] = Time.now
11
14
  end
12
15
 
13
16
  def response
@@ -45,6 +48,14 @@ module Specwrk
45
48
  def completed_queue
46
49
  Web::COMPLETED_QUEUES[request.get_header("HTTP_X_SPECWRK_RUN")]
47
50
  end
51
+
52
+ def workers
53
+ Web::WORKERS[request.get_header("HTTP_X_SPECWRK_RUN")]
54
+ end
55
+
56
+ def worker
57
+ workers[request.get_header("HTTP_X_SPECWRK_ID")]
58
+ end
48
59
  end
49
60
 
50
61
  # Base default response is 404
@@ -135,25 +146,7 @@ module Specwrk
135
146
 
136
147
  class Shutdown < Base
137
148
  def response
138
- if ENV["SPECWRK_SRV_SINGLE_RUN"]
139
- interupt!
140
- elsif processing_queue.length.positive?
141
- # Push any processing jobs back into the pending queue
142
- processing_queue.synchronize do |processing_queue_hash|
143
- pending_queue.synchronize do |pending_queue_hash|
144
- processing_queue_hash.each do |id, example|
145
- pending_queue_hash[id] = example
146
- processing_queue_hash.delete(id)
147
- end
148
- end
149
- end
150
-
151
- elsif processing_queue.length.zero? && pending_queue.length.zero?
152
- # All done, we can clear the completed queue
153
- completed_queue.clear
154
- end
155
-
156
- # TODO: clear any zombie queues
149
+ interupt! if ENV["SPECWRK_SRV_SINGLE_RUN"]
157
150
 
158
151
  [200, {"Content-Type" => "text/plain"}, ["✌️"]]
159
152
  end
data/lib/specwrk/web.rb CHANGED
@@ -7,9 +7,16 @@ module Specwrk
7
7
  PENDING_QUEUES = Queue.new { |h, key| h[key] = PendingQueue.new.tap { |q| q.previous_run_times_file = ENV["SPECWRK_SRV_OUTPUT"] } }
8
8
  PROCESSING_QUEUES = Queue.new { |h, key| h[key] = Queue.new }
9
9
  COMPLETED_QUEUES = Queue.new { |h, key| h[key] = CompletedQueue.new }
10
+ WORKERS = Hash.new { |h, key| h[key] = Hash.new { |h, key| h[key] = {} } }
10
11
 
11
12
  def self.clear_queues
12
- [PENDING_QUEUES, PROCESSING_QUEUES, COMPLETED_QUEUES].each(&:clear)
13
+ [PENDING_QUEUES, PROCESSING_QUEUES, COMPLETED_QUEUES, WORKERS].each(&:clear)
14
+ end
15
+
16
+ def self.clear_run_queues(run)
17
+ [PENDING_QUEUES, PROCESSING_QUEUES, COMPLETED_QUEUES, WORKERS].each do |queue|
18
+ queue.delete(run)
19
+ end
13
20
  end
14
21
  end
15
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: specwrk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.11
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Westendorf