specwrk 0.1.1 → 0.1.2

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: f06b10c3a81644d436c6b7b636c97c83b2b5bbb4c43065fa4a27554a5870b873
4
- data.tar.gz: '002619c27e85bbd6abaab2cb86a6e622549f20e5548087c87908421eb4aa78e4'
3
+ metadata.gz: 2c16c0b37ed56096253bc295ee77360813c5d1363a68cbd75f3694545448a588
4
+ data.tar.gz: 365e391b1075fead8b38c00ba57d307c0ee47107acec2a946d2c9484abe89fee
5
5
  SHA512:
6
- metadata.gz: 61735c8eebc5bd13bdaafefd0925ed597b102fdb785bb821437bfb415654907a6262f11b8c2710b9c3913a6752816b4381c9315c55b0959877abb89e16280b46
7
- data.tar.gz: 97773a5c2e828e6fbf4562aa6eaea2e5f9ac9cf6e733959cb634b18e984e7e1ee48384eb5aa170bd89cd4de41f17cb14f372b6057e6ecbfc3c64cf9bcb3491fc
6
+ metadata.gz: 28ecd7dd329f4ca7db54c27fbf1454810c8cf06966c8317e51611820c9ab39adba812377ec2ac99e2c9d902b5456a60e4696545662e2952c2768bdc2a6777477
7
+ data.tar.gz: 642b25bcf069fd689472c408408baa48e25b9fe8bb32989b89b68e68f210381c9f0e9b160d2c6207e700c356bd9a668b30ae29f093b1c69c0dd42debaf02b72b
data/exe/specwrk CHANGED
@@ -5,7 +5,7 @@ require "specwrk/cli"
5
5
 
6
6
  trap("INT") do
7
7
  if Specwrk.starting_pid == Process.pid && !Specwrk.force_quit
8
- warn "Waiting for in-progress work to finish. Interrupt again to force quit (warning: at_exit hooks will be skipped if you force quit)."
8
+ warn "Waiting for in-progress work to finish. Interrupt again to force quit (warning: at_exit hooks will be skipped if you force quit)."
9
9
 
10
10
  Specwrk.force_quit = true
11
11
  elsif Specwrk.starting_pid != Process.pid
data/lib/specwrk/cli.rb CHANGED
@@ -15,10 +15,10 @@ module Specwrk
15
15
  extend Hookable
16
16
 
17
17
  on_included do |base|
18
- base.option :uri, type: :string, default: ENV.fetch("SPECWRK_SRV_URI", "https://localhost:#{ENV.fetch("SPECWRK_SRV_PORT", "5138")}"), desc: "HTTP URI of the server to pull jobs from"
19
- base.option :key, type: :string, default: ENV.fetch("SPECWRK_SRV_KEY", ""), aliases: ["-k"], desc: "Authentication key for accessing the server"
20
- base.option :run, type: :string, default: ENV.fetch("SPECWRK_SRV_KEY", "main"), aliases: ["-r"], desc: "The run identifier for this job execution"
21
- base.option :timeout, type: :integer, default: ENV.fetch("SPECWRK_TIMEOUT", "5"), aliases: ["-t"], desc: "The amount of time to wait for the server to respond"
18
+ base.unique_option :uri, type: :string, default: ENV.fetch("SPECWRK_SRV_URI", "https://localhost:#{ENV.fetch("SPECWRK_SRV_PORT", "5138")}"), desc: "HTTP URI of the server to pull jobs from. Overrides SPECWRK_SRV_PORT. Default 5138."
19
+ base.unique_option :key, type: :string, default: ENV.fetch("SPECWRK_SRV_KEY", ""), aliases: ["-k"], desc: "Authentication key clients must use for access. Overrides SPECWRK_SRV_KEY. Default ''."
20
+ base.unique_option :run, type: :string, default: ENV.fetch("SPECWRK_RUN", "main"), aliases: ["-r"], desc: "The run identifier for this job execution. Overrides SPECWRK_RUN. Default main."
21
+ base.unique_option :timeout, type: :integer, default: ENV.fetch("SPECWRK_TIMEOUT", "5"), aliases: ["-t"], desc: "The amount of time to wait for the server to respond. Overrides SPECWRK_TIMEOUT. Default 5."
22
22
  end
23
23
 
24
24
  on_setup do |uri:, key:, run:, timeout:, **|
@@ -33,9 +33,9 @@ module Specwrk
33
33
  extend Hookable
34
34
 
35
35
  on_included do |base|
36
- base.option :id, type: :string, default: "specwrk-worker", desc: "The identifier for this worker"
37
- base.option :count, type: :integer, default: 1, aliases: ["-c"], desc: "The number of worker processes you want to start"
38
- base.option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored"
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 :count, type: :integer, default: 1, aliases: ["-c"], desc: "The number of worker processes you want to start. Default 1."
38
+ base.unique_option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored. Overrides SPECWRK_OUT. Default '.specwrk/'."
39
39
  end
40
40
 
41
41
  on_setup do |id:, count:, output:, **|
@@ -66,14 +66,16 @@ module Specwrk
66
66
  extend Hookable
67
67
 
68
68
  on_included do |base|
69
- base.option :port, type: :integer, default: ENV.fetch("SPECWRK_SRV_PORT", "5138"), aliases: ["-p"], desc: "Server port"
70
- base.option :key, type: :string, aliases: ["-k"], default: ENV.fetch("SPECWRK_SRV_KEY", ""), desc: "Authentication key clients must use for access"
71
- base.option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored"
72
- base.option :single_run, type: :boolean, default: !ENV["SPECWRK_SRV_SINGLE_RUN"].nil?, desc: "Act on shutdown requests from clients"
73
- base.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"
69
+ base.unique_option :port, type: :integer, default: ENV.fetch("SPECWRK_SRV_PORT", "5138"), aliases: ["-p"], desc: "Server port. Overrides SPECWRK_SRV_PORT. Default 5138."
70
+ 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. Default ''."
71
+ base.unique_option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored. Overrides SPECWRK_OUT. Default '.specwrk/'."
72
+ 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. Default timings."
73
+ base.unique_option :single_run, type: :boolean, default: false, desc: "Act on shutdown requests from clients. Default: false."
74
+ base.unique_option :verbose, type: :boolean, default: false, desc: "Run in verbose mode. Default false."
74
75
  end
75
76
 
76
- on_setup do |output:, port:, key:, single_run:, group_by:, **|
77
+ on_setup do |output:, port:, key:, single_run:, group_by:, verbose:, **|
78
+ ENV["SPECWRK_SRV_LOG"] = Pathname.new(File.join(output, "server.log")).expand_path(Dir.pwd).to_s if output && !verbose
77
79
  ENV["SPECWRK_SRV_OUTPUT"] = Pathname.new(File.join(output, "report.json")).expand_path(Dir.pwd).to_s if output
78
80
  ENV["SPECWRK_SRV_PORT"] = port
79
81
  ENV["SPECWRK_SRV_KEY"] = key
@@ -136,7 +138,7 @@ module Specwrk
136
138
  class Serve < Dry::CLI::Command
137
139
  include Servable
138
140
 
139
- desc "Start a server"
141
+ desc "Start a queue server"
140
142
 
141
143
  def call(**args)
142
144
  self.class.setup(**args)
@@ -170,6 +172,7 @@ module Specwrk
170
172
  Specwrk::Web::App.run!
171
173
  end
172
174
 
175
+ return if Specwrk.force_quit
173
176
  seed_pid = Process.fork do
174
177
  require "specwrk/list_examples"
175
178
  require "specwrk/client"
@@ -186,12 +189,15 @@ module Specwrk
186
189
 
187
190
  wait_for_pids_exit([seed_pid])
188
191
 
192
+ return if Specwrk.force_quit
189
193
  status "Starting #{worker_count} workers..."
190
194
  start_workers
191
195
 
192
196
  status "#{worker_count} workers started ✓\n"
193
197
  wait_for_pids_exit(@worker_pids)
194
198
 
199
+ return if Specwrk.force_quit
200
+
195
201
  require "specwrk/cli_reporter"
196
202
  status = Specwrk::CLIReporter.new.report
197
203
 
@@ -35,6 +35,10 @@ module Hookable
35
35
  end
36
36
 
37
37
  module ClassMethods
38
+ def unique_option(name, opts = {})
39
+ option(name, opts) unless options.find { |existing_option| existing_option.name == name }
40
+ end
41
+
38
42
  def setup(**args)
39
43
  setup_hooks.each { |blk| blk.call(**args) }
40
44
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Specwrk
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.2"
5
5
  end
@@ -10,33 +10,49 @@ rescue LoadError
10
10
  require "rack/handler/webrick"
11
11
  end
12
12
 
13
+ require "specwrk/web/logger"
13
14
  require "specwrk/web/auth"
14
15
  require "specwrk/web/endpoints"
15
16
 
16
17
  module Specwrk
17
18
  class Web
18
19
  class App
19
- def self.run!
20
- Process.setproctitle "specwrk-server"
20
+ class << self
21
+ def run!
22
+ Process.setproctitle "specwrk-server"
21
23
 
22
- server_opts = {
23
- Port: ENV.fetch("SPECWRK_SRV_PORT", "5138").to_i,
24
- Logger: WEBrick::Log.new($stdout, WEBrick::Log::FATAL),
25
- AccessLog: [],
26
- KeepAliveTimeout: 300
27
- }
24
+ if ENV["SPECWRK_SRV_LOG"]
25
+ $stdout.reopen(ENV["SPECWRK_SRV_LOG"], "w")
26
+ end
27
+
28
+ server_opts = {
29
+ Port: ENV.fetch("SPECWRK_SRV_PORT", "5138").to_i,
30
+ Logger: WEBrick::Log.new($stdout, WEBrick::Log::FATAL),
31
+ AccessLog: [],
32
+ KeepAliveTimeout: 300
33
+ }
28
34
 
29
- # rack v3 or v2
30
- handler_klass = defined?(Rackup::Handler) ? Rackup::Handler::WEBrick : Rack::Handler.get("webrick")
35
+ # rack v3 or v2
36
+ handler_klass = defined?(Rackup::Handler) ? Rackup::Handler::WEBrick : Rack::Handler.get("webrick")
31
37
 
32
- handler_klass.run(rackup, **server_opts) do |server|
33
- ["INT", "TERM"].each do |sig|
34
- trap(sig) do
35
- puts "\n→ Shutting down gracefully..." unless ENV["SPECWRK_FORKED"]
36
- server.shutdown
38
+ handler_klass.run(rackup, **server_opts) do |server|
39
+ ["INT", "TERM"].each do |sig|
40
+ trap(sig) do
41
+ puts "\n→ Shutting down gracefully..." unless ENV["SPECWRK_FORKED"]
42
+ server.shutdown
43
+ end
37
44
  end
38
45
  end
39
46
  end
47
+
48
+ def rackup
49
+ Rack::Builder.new do
50
+ use Rack::Runtime
51
+ use Specwrk::Web::Logger, $stdout
52
+ use Specwrk::Web::Auth # global auth check
53
+ run Specwrk::Web::App.new # your router
54
+ end
55
+ end
40
56
  end
41
57
 
42
58
  def call(env)
@@ -47,13 +63,6 @@ module Specwrk
47
63
  .response
48
64
  end
49
65
 
50
- private_class_method def self.rackup
51
- Rack::Builder.new do
52
- use Specwrk::Web::Auth # global auth check
53
- run Specwrk::Web::App.new # your router
54
- end
55
- end
56
-
57
66
  def route(method:, path:)
58
67
  case [method, path]
59
68
  when ["GET", "/heartbeat"]
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Specwrk
4
+ class Web
5
+ class Logger
6
+ def initialize(app, out = $stdout)
7
+ @app, @out = app, out
8
+ end
9
+
10
+ def call(env)
11
+ start_time = Time.now
12
+ start = Process.clock_gettime(Process::CLOCK_MONOTONIC)
13
+ status, headers, body = @app.call(env)
14
+ dur_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - start) * 1000).round(4)
15
+
16
+ remote = env["REMOTE_ADDR"] || env["REMOTE_HOST"] || "-"
17
+ @out.puts "#{remote} [#{start_time.iso8601(6)}] #{env["REQUEST_METHOD"]} #{env["PATH_INFO"]} → #{status} (#{dur_ms}ms)"
18
+ [status, headers, body]
19
+ end
20
+ end
21
+ end
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.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Westendorf
@@ -147,6 +147,7 @@ files:
147
147
  - lib/specwrk/web/app.rb
148
148
  - lib/specwrk/web/auth.rb
149
149
  - lib/specwrk/web/endpoints.rb
150
+ - lib/specwrk/web/logger.rb
150
151
  - lib/specwrk/worker.rb
151
152
  - lib/specwrk/worker/completion_formatter.rb
152
153
  - lib/specwrk/worker/executor.rb