specwrk 0.9.1 → 0.10.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: 657cd8e611ea7ea6344dc5bd540892e69d801ea5afd410b1be2e7a6d3f73658e
4
- data.tar.gz: c066775a6f57452cd55c49eec7604b8e264881ad085d7847ff176240a9ecbe05
3
+ metadata.gz: 656884cedc1e6851a42054d696fb0c8cbb3c7afffa48935340c973d824cc6cc0
4
+ data.tar.gz: e8b562b8070e5342d6343b299a80fe0bc98a17060632aa369f5ded91ffecb820
5
5
  SHA512:
6
- metadata.gz: 076a41a98119ccfe0108c76c32341d8cbf6642da3f37f80276a61ed885fbca9ddaf31c597b8462ddeb608c67d7e8787f5cefd606cb4b977aeef715e9a5cdb0bb
7
- data.tar.gz: 39891db9a0400196ddaba587e7014aa00e485c65ce37efc997998f854dd98d8cabfef39806657bec15e71c43a29743dda4081b35c2022a917a5503e4e161cea4
6
+ metadata.gz: a536a0bf7de4959ca820afa5e9249024181f198d073ca648f040f8f4276f63572ac74a1cdff481b9e050b1983f7af7eac5b2d31c3271dff911ae88aa75092f27
7
+ data.tar.gz: eddaa254e6254727f950006b30b653402a33acd827b1060baf583840d99ae2d41dec0ab4a15c11754c03db3f2664ea348efefc1b32b95b494c56287a0d3b88d0
data/README.md CHANGED
@@ -58,7 +58,6 @@ Options:
58
58
  --port=VALUE, -p VALUE # Server port. Overrides SPECWRK_SRV_PORT, default: "5138"
59
59
  --bind=VALUE, -b VALUE # Server bind address. Overrides SPECWRK_SRV_BIND, default: "127.0.0.1"
60
60
  --group-by=VALUE # How examples will be grouped for workers; fallback to file if no timings are found. Overrides SPECWERK_SRV_GROUP_BY: (file/timings), default: "timings"
61
- --[no-]single-seed-per-run # Only allow one seed per run. Useful for CI where many nodes may seed at the same time, default: false
62
61
  --[no-]verbose # Run in verbose mode. Default false., default: false
63
62
  --help, -h # Print this help
64
63
  ```
@@ -83,7 +82,6 @@ Options:
83
82
  --key=VALUE, -k VALUE # Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY, default: ""
84
83
  --output=VALUE, -o VALUE # Directory where worker output is stored. Overrides SPECWRK_OUT, default: ".specwrk/"
85
84
  --group-by=VALUE # How examples will be grouped for workers; fallback to file if no timings are found. Overrides SPECWERK_SRV_GROUP_BY: (file/timings), default: "timings"
86
- --[no-]single-seed-per-run # Only allow one seed per run. Useful for CI where many nodes may seed at the same time, default: false
87
85
  --[no-]verbose # Run in verbose mode. Default false., default: false
88
86
  --[no-]single-run # Act on shutdown requests from clients. Default: false., default: false
89
87
  --help, -h # Print this help
data/lib/specwrk/cli.rb CHANGED
@@ -76,7 +76,6 @@ module Specwrk
76
76
  base.unique_option :key, type: :string, aliases: ["-k"], default: ENV.fetch("SPECWRK_SRV_KEY", ""), desc: "Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY"
77
77
  base.unique_option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored. Overrides SPECWRK_OUT"
78
78
  base.unique_option :group_by, values: %w[file timings], default: ENV.fetch("SPECWERK_SRV_GROUP_BY", "timings"), desc: "How examples will be grouped for workers; fallback to file if no timings are found. Overrides SPECWERK_SRV_GROUP_BY"
79
- base.unique_option :single_seed_per_run, type: :boolean, default: false, desc: "Only allow one seed per run. Useful for CI where many nodes may seed at the same time"
80
79
  base.unique_option :verbose, type: :boolean, default: false, desc: "Run in verbose mode. Default false."
81
80
  end
82
81
 
@@ -211,7 +210,8 @@ module Specwrk
211
210
  status "Server responding ✓"
212
211
  status "Seeding #{examples.length} examples..."
213
212
  Client.new.seed(examples)
214
- status "Samples seeded ✓"
213
+ file_count = examples.group_by { |e| e[:file_path] }.keys.size
214
+ status "🌱 Seeded #{examples.size} examples across #{file_count} files"
215
215
  end
216
216
 
217
217
  if Specwrk.wait_for_pids_exit([seed_pid]).value?(1)
@@ -105,6 +105,23 @@ module Specwrk
105
105
  (response.code == "200") ? true : raise(UnhandledResponseError.new("#{response.code}: #{response.body}"))
106
106
  end
107
107
 
108
+ def complete_and_fetch_examples(examples)
109
+ response = post "/complete_and_pop", body: examples.to_json
110
+
111
+ case response.code
112
+ when "200"
113
+ JSON.parse(response.body, symbolize_names: true)
114
+ when "204"
115
+ raise WaitingForSeedError
116
+ when "404"
117
+ raise NoMoreExamplesError
118
+ when "410"
119
+ raise CompletedAllExamplesError
120
+ else
121
+ raise UnhandledResponseError.new("#{response.code}: #{response.body}")
122
+ end
123
+ end
124
+
108
125
  def seed(examples)
109
126
  response = post "/seed", body: examples.to_json
110
127
 
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specwrk
4
- VERSION = "0.9.1"
4
+ VERSION = "0.10.0"
5
5
  end
@@ -90,6 +90,8 @@ module Specwrk
90
90
  Endpoints::Pop
91
91
  when ["POST", "/complete"]
92
92
  Endpoints::Complete
93
+ when ["POST", "/complete_and_pop"]
94
+ Endpoints::CompleteAndPop
93
95
  when ["POST", "/seed"]
94
96
  Endpoints::Seed
95
97
  when ["GET", "/report"]
@@ -137,17 +137,15 @@ module Specwrk
137
137
 
138
138
  class Seed < Base
139
139
  def before_lock
140
- examples_with_run_times if persist_seeds?
140
+ examples_with_run_times
141
141
  end
142
142
 
143
143
  def with_response
144
- if persist_seeds?
145
- new_run_time_bucket_maximums = [pending.run_time_bucket_maximum, @seeds_run_time_bucket_maximum.to_f].compact
146
- pending.run_time_bucket_maximum = new_run_time_bucket_maximums.sum.to_f / new_run_time_bucket_maximums.length.to_f
147
-
148
- pending.merge!(examples_with_run_times)
149
- end
144
+ pending.clear
145
+ new_run_time_bucket_maximums = [pending.run_time_bucket_maximum, @seeds_run_time_bucket_maximum.to_f].compact
146
+ pending.run_time_bucket_maximum = new_run_time_bucket_maximums.sum.to_f / new_run_time_bucket_maximums.length.to_f
150
147
 
148
+ pending.merge!(examples_with_run_times)
151
149
  processing.clear
152
150
  completed.clear
153
151
 
@@ -192,10 +190,6 @@ module Specwrk
192
190
  (mean + Math.sqrt(variance)).round(2)
193
191
  end
194
192
 
195
- def persist_seeds?
196
- ENV["SPECWRK_SRV_SINGLE_SEED_PER_RUN"].nil? || pending.empty?
197
- end
198
-
199
193
  def sort_by
200
194
  if ENV["SPECWRK_SRV_GROUP_BY"] == "file" || run_times.empty?
201
195
  :file
@@ -207,6 +201,7 @@ module Specwrk
207
201
 
208
202
  class Complete < Base
209
203
  def with_response
204
+ warn "[DEPRECATED] This endpoint will be retired in favor of CompleteAndPop. Upgrade your clients."
210
205
  completed.merge!(completed_examples)
211
206
  processing.delete(*completed_examples.keys)
212
207
 
@@ -246,6 +241,51 @@ module Specwrk
246
241
  end
247
242
  end
248
243
 
244
+ class CompleteAndPop < Base
245
+ def with_response
246
+ completed.merge!(completed_examples)
247
+ run_times.merge! run_time_data
248
+ processing.delete(*completed_examples.keys)
249
+
250
+ @examples = pending.shift_bucket
251
+
252
+ processing_data = @examples.map { |example| [example[:id], example] }.to_h
253
+ processing.merge!(processing_data)
254
+
255
+ if @examples.any?
256
+ [200, {"Content-Type" => "application/json"}, [JSON.generate(@examples)]]
257
+ elsif pending.empty? && processing.empty? && completed.empty?
258
+ [204, {"Content-Type" => "text/plain"}, ["Waiting for sample to be seeded."]]
259
+ elsif completed.any? && processing.empty?
260
+ [410, {"Content-Type" => "text/plain"}, ["That's a good lad. Run along now and go home."]]
261
+ else
262
+ not_found
263
+ end
264
+ end
265
+
266
+ private
267
+
268
+ def before_lock
269
+ completed_examples
270
+ run_time_data
271
+ end
272
+
273
+ def completed_examples
274
+ @completed_data ||= payload.map { |example| [example[:id], example] if processing[example[:id]] }.compact.to_h
275
+ end
276
+
277
+ # We don't care about exact values here, just approximate run times are fine
278
+ # So if we overwrite run times from another process it is nbd
279
+ def after_lock
280
+ # run_time_data = payload.map { |example| [example[:id], example[:run_time]] }.to_h
281
+ # run_times.merge! run_time_data
282
+ end
283
+
284
+ def run_time_data
285
+ @run_time_data ||= payload.map { |example| [example[:id], example[:run_time]] }.to_h
286
+ end
287
+ end
288
+
249
289
  class Report < Base
250
290
  def with_response
251
291
  [200, {"Content-Type" => "application/json"}, [JSON.generate(completed.dump)]]
@@ -69,15 +69,21 @@ module Specwrk
69
69
  end
70
70
 
71
71
  def execute
72
- executor.run client.fetch_examples
72
+ executor.run next_examples
73
73
  complete_examples
74
74
  rescue UnhandledResponseError => e
75
- # If fetching examples fails we can just try again so warn and return
75
+ # If fetching examples via next_exampels fails we can just try again so warn and return
76
+ # Expects complete_examples to rescue this error if raised in that method
76
77
  warn e.message
77
78
  end
78
79
 
80
+ def next_examples
81
+ return @next_examples if @next_examples&.length&.positive?
82
+ client.fetch_examples
83
+ end
84
+
79
85
  def complete_examples
80
- client.complete_examples executor.examples
86
+ @next_examples = client.complete_and_fetch_examples executor.examples
81
87
  rescue UnhandledResponseError => e
82
88
  # I do not think we should so lightly abandon the completion of executed examples
83
89
  # try to complete until successful or terminated
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.9.1
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Westendorf