specwrk 0.1.0 → 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: 6f2753749c4fdc2460290c8ead228965ba766624fe19b52119e6769f682a7681
4
- data.tar.gz: 0b773de7c6366e102fc1299630e9aeb983f8284c75f392fd733dc6a8fc714af8
3
+ metadata.gz: 2c16c0b37ed56096253bc295ee77360813c5d1363a68cbd75f3694545448a588
4
+ data.tar.gz: 365e391b1075fead8b38c00ba57d307c0ee47107acec2a946d2c9484abe89fee
5
5
  SHA512:
6
- metadata.gz: 0014b21f279efc09cfd4edf3e5cc5b472ac46096966bc9f487ceeed3f1d1d20dfcf567122a13a594792e98fb33536bd8e51310814a38af96c9f6c3bf628372f0
7
- data.tar.gz: 066dfcb0decca0dd8a3cb10b73acbcd6f791ff16ec1a9e2ca8ea4a56d95a5b2d23a56e88ff95dc5780c5fa3b529ea122edfb2b82fcb56c9e6b02a59545fd2a28
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
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "pathname"
4
+
3
5
  require "dry/cli"
4
6
 
5
7
  require "specwrk"
@@ -13,10 +15,10 @@ module Specwrk
13
15
  extend Hookable
14
16
 
15
17
  on_included do |base|
16
- 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"
17
- base.option :key, type: :string, default: ENV.fetch("SPECWRK_SRV_KEY", ""), aliases: ["-k"], desc: "Authentication key for accessing the server"
18
- base.option :run, type: :string, default: ENV.fetch("SPECWRK_SRV_KEY", "main"), aliases: ["-r"], desc: "The run identifier for this job execution"
19
- 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."
20
22
  end
21
23
 
22
24
  on_setup do |uri:, key:, run:, timeout:, **|
@@ -31,9 +33,9 @@ module Specwrk
31
33
  extend Hookable
32
34
 
33
35
  on_included do |base|
34
- base.option :id, type: :string, default: "specwrk-worker", desc: "The identifier for this worker"
35
- base.option :count, type: :integer, default: 1, aliases: ["-c"], desc: "The number of worker processes you want to start"
36
- 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/'."
37
39
  end
38
40
 
39
41
  on_setup do |id:, count:, output:, **|
@@ -64,14 +66,16 @@ module Specwrk
64
66
  extend Hookable
65
67
 
66
68
  on_included do |base|
67
- base.option :port, type: :integer, default: ENV.fetch("SPECWRK_SRV_PORT", "5138"), aliases: ["-p"], desc: "Server port"
68
- base.option :key, type: :string, aliases: ["-k"], default: ENV.fetch("SPECWRK_SRV_KEY", ""), desc: "Authentication key clients must use for access"
69
- base.option :output, type: :string, default: ENV.fetch("SPECWRK_OUT", ".specwrk/"), aliases: ["-o"], desc: "Directory where worker output is stored"
70
- base.option :single_run, type: :boolean, default: !ENV["SPECWRK_SRV_SINGLE_RUN"].nil?, desc: "Act on shutdown requests from clients"
71
- 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."
72
75
  end
73
76
 
74
- 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
75
79
  ENV["SPECWRK_SRV_OUTPUT"] = Pathname.new(File.join(output, "report.json")).expand_path(Dir.pwd).to_s if output
76
80
  ENV["SPECWRK_SRV_PORT"] = port
77
81
  ENV["SPECWRK_SRV_KEY"] = key
@@ -134,7 +138,7 @@ module Specwrk
134
138
  class Serve < Dry::CLI::Command
135
139
  include Servable
136
140
 
137
- desc "Start a server"
141
+ desc "Start a queue server"
138
142
 
139
143
  def call(**args)
140
144
  self.class.setup(**args)
@@ -168,6 +172,7 @@ module Specwrk
168
172
  Specwrk::Web::App.run!
169
173
  end
170
174
 
175
+ return if Specwrk.force_quit
171
176
  seed_pid = Process.fork do
172
177
  require "specwrk/list_examples"
173
178
  require "specwrk/client"
@@ -184,12 +189,15 @@ module Specwrk
184
189
 
185
190
  wait_for_pids_exit([seed_pid])
186
191
 
192
+ return if Specwrk.force_quit
187
193
  status "Starting #{worker_count} workers..."
188
194
  start_workers
189
195
 
190
196
  status "#{worker_count} workers started ✓\n"
191
197
  wait_for_pids_exit(@worker_pids)
192
198
 
199
+ return if Specwrk.force_quit
200
+
193
201
  require "specwrk/cli_reporter"
194
202
  status = Specwrk::CLIReporter.new.report
195
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.0"
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.0
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