lavin 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d3a7216c049391b24ccad2eb6c6d6424114761a11b1b4aa15824c5c58ca2bf19
4
- data.tar.gz: 3ec27a41fdc255d3eafb3a168c39ad8b744b28ab5e436d38d8eaf9f94aa22f23
3
+ metadata.gz: 52a0a48c405e0aff4b816ff7bf91b27e8407929a838db819f8777d222b4f7674
4
+ data.tar.gz: 4acb3c0a928acd45ecbd8137089433e69cdc8235919a0db6fefefb40418bfd82
5
5
  SHA512:
6
- metadata.gz: c6689ccce7532d8438013a8e3af32052f5b8df828169a026270f03d16a9078f11677b36f2a6c8989ec27cd8bfa3248d4bb1a9bbd2ddc35cccd4d8f1df143e182
7
- data.tar.gz: 4b2b728d3d5c775471c3ffdcf52c7b2a475d6c7e76d6aae4288b1e1154747e6f81bc802bf3f04f951aa1dec02de690671f110e01db8baed5c5442717f93f2b85
6
+ metadata.gz: e2fe666e13f22d13dc4f085e8ab7e78c2242a973bd9b0d58054e0b4ada2cc17d1ca924e4103a3c55408bd88c4d1cd3efa8b3449cee7fd8a5d36794392218779c
7
+ data.tar.gz: b1f7f478a288492082a4f02462d345ce42703316638b3d6aee7848a92a539b22b750105e5e70fdf2ffe662ac26ed68a4f6a32c63154b18ba4faf96dee917b16b
checksums.yaml.gz.sig CHANGED
Binary file
data/lib/lavin/client.rb CHANGED
@@ -5,6 +5,13 @@ require 'async/http/internet'
5
5
  module Lavin
6
6
  class Client
7
7
  class Error < Lavin::Error; end
8
+
9
+ class ServerError < Error
10
+ def initialize(status)
11
+ super("Server responded with status: #{status}")
12
+ end
13
+ end
14
+
8
15
  class NoCurrentAsyncTaskError < Error
9
16
  def initialize(msg = nil)
10
17
  super(msg || "Trying to create a client outside of an Async task")
data/lib/lavin/error.rb CHANGED
@@ -2,4 +2,8 @@
2
2
 
3
3
  module Lavin
4
4
  class Error < StandardError; end
5
+
6
+ class RecoverableError < Error; end
7
+
8
+ class IrrecoverableError < Error; end
5
9
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'lavin/error'
4
+
5
+ module Lavin
6
+ module Failure
7
+ def failure(msg)
8
+ raise RecoverableError, msg
9
+ end
10
+
11
+ def failure!(msg)
12
+ raise IrrecoverableError, msg
13
+ end
14
+ end
15
+ end
data/lib/lavin/hook.rb CHANGED
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
- #
3
2
 
4
3
  module Lavin
5
4
  class Hook
6
- attr_reader :user, :block
5
+ attr_reader :user, :block, :type
7
6
 
8
- def initialize(user:, &block)
7
+ def initialize(user:, type: :before, &block)
9
8
  @user = user
10
9
  @block = block
10
+ @type = type
11
11
  end
12
12
 
13
13
  def run(context: nil)
@@ -19,9 +19,11 @@ module Lavin
19
19
  report_statistics = context.client.report_statistics
20
20
  context.client.report_statistics = false
21
21
  context.instance_exec(&block)
22
+ rescue RecoverableError
22
23
  rescue => error
23
- puts "Caught an error - #{error.class}: #{error.message}"
24
- puts error.backtrace
24
+ puts "Caught #{error.class} in #{type} hook: #{error.message}"
25
+ puts error.backtrace unless error.is_a? IrrecoverableError
26
+ throw :failure
25
27
  ensure
26
28
  context.client.report_statistics = report_statistics
27
29
  end
@@ -17,27 +17,35 @@ module Lavin
17
17
  end
18
18
 
19
19
  def get(url, headers: {})
20
- client.request(:get, url:, headers:)
20
+ request(:get, url:, headers:)
21
21
  end
22
22
 
23
23
  def head(url, headers: {})
24
- client.request(:head, url:, headers:)
24
+ request(:head, url:, headers:)
25
25
  end
26
26
 
27
27
  def post(url, headers: {}, body: nil)
28
- client.request(:post, url:, headers:, body:)
28
+ request(:post, url:, headers:, body:)
29
29
  end
30
30
 
31
31
  def put(url, headers: {}, body: nil)
32
- client.request(:put, url:, headers:, body:)
32
+ request(:put, url:, headers:, body:)
33
33
  end
34
34
 
35
35
  def patch(url, headers: {}, body: nil)
36
- client.request(:patch, url:, headers:, body:)
36
+ request(:patch, url:, headers:, body:)
37
37
  end
38
38
 
39
39
  def delete(url, headers: {})
40
- client.request(:delete, url:, headers:)
40
+ request(:delete, url:, headers:)
41
+ end
42
+
43
+ private
44
+
45
+ def request(method, url:, headers:, body: nil)
46
+ client.request(method, url:, headers:, body:).tap do |response|
47
+ raise Lavin::Client::ServerError, response[:status] if response[:status] > 499
48
+ end
41
49
  end
42
50
  end
43
51
  end
data/lib/lavin/runner.rb CHANGED
@@ -62,9 +62,9 @@ module Lavin
62
62
  end
63
63
 
64
64
  def stop
65
- Statistics.stop
66
65
  thread&.kill
67
66
  self.thread = nil
67
+ Statistics.stop
68
68
  end
69
69
 
70
70
  def running?
@@ -53,6 +53,7 @@ module Lavin
53
53
  key = [user, step_name]
54
54
  data[:steps][key][:success] += 1 unless failure
55
55
  data[:steps][key][:failure] += 1 if failure
56
+ data[:failures][failure.to_s] += 1 if failure
56
57
  end
57
58
 
58
59
  def stats
@@ -62,9 +63,11 @@ module Lavin
62
63
  requests = data[:requests].map do |(method, url), requests|
63
64
  durations = []
64
65
  statuses = []
66
+ failed_requests = 0
65
67
  requests.each do |request|
66
68
  durations << request[:duration]
67
69
  statuses << request[:status]
70
+ failed_requests += 1 if request[:failure]
68
71
  end
69
72
  min_duration = durations.min
70
73
  max_duration = durations.max
@@ -75,9 +78,10 @@ module Lavin
75
78
  url: url,
76
79
  requests: requests.size,
77
80
  statuses: statuses.tally,
78
- avg_duration: avg_duration,
79
- min_duration: min_duration,
80
- max_duration: max_duration
81
+ failed_requests:,
82
+ avg_duration:,
83
+ min_duration:,
84
+ max_duration:
81
85
  }
82
86
  end
83
87
 
@@ -87,7 +91,8 @@ module Lavin
87
91
  rate: duration ? format("%.2f", total_requests / duration) : 0,
88
92
  step_summary: data[:step_summary],
89
93
  steps: data[:steps],
90
- requests: requests
94
+ requests: requests,
95
+ failures: data[:failures]
91
96
  ).tap do |stats|
92
97
  # FIXME remove!
93
98
  puts "Calculated stats in #{Time.now - time}s"
@@ -101,7 +106,7 @@ module Lavin
101
106
 
102
107
  show_steps(values) do |(user, step), hash|
103
108
  format(
104
- "%-24<user_step>s %8<success>d %8<failure>d",
109
+ "%-48<user_step>s %8<success>d %8<failure>d",
105
110
  user_step: "#{user}.#{step}",
106
111
  **hash
107
112
  )
@@ -113,6 +118,10 @@ module Lavin
113
118
  **request_values
114
119
  )
115
120
  end
121
+
122
+ show_failures(values) do |message, count|
123
+ format("%-64<message>s %6<count>d", message:, count:)
124
+ end
116
125
  end
117
126
 
118
127
  private
@@ -141,7 +150,8 @@ module Lavin
141
150
  failure: 0
142
151
  },
143
152
  steps: Hash.new { |h, k| h[k] = {success: 0, failure: 0} },
144
- requests: Hash.new { |h, k| h[k] = [] }
153
+ requests: Hash.new { |h, k| h[k] = [] },
154
+ failures: Hash.new { |h, k| h[k] = 0 }
145
155
  }
146
156
  end
147
157
 
@@ -155,26 +165,25 @@ module Lavin
155
165
 
156
166
  Total number of steps: #{values.total_steps}
157
167
  Step success rate: #{format("%.2f %%", 100 * values.successful_steps.to_f / values.total_steps)}
158
-
159
168
  RESULT
160
169
  end
161
170
 
162
171
  def show_steps(values)
163
172
  puts format(
164
- "%-24<user_step>s %8<success>s %8<failure>s",
173
+ "\n%-48<user_step>s %8<success>s %8<failure>s",
165
174
  user_step: "Steps",
166
175
  success: "Success",
167
176
  failure: "Failure"
168
177
  )
169
- divider = "-" * 42
178
+ divider = "-" * 66
170
179
  puts divider
171
180
  values.each_step { |step_values| puts yield step_values }
172
- puts "#{divider}\n\n"
181
+ puts divider
173
182
  end
174
183
 
175
184
  def show_table(values)
176
185
  puts format(
177
- "%-6<method>s %-100<url>s %-6<requests>s %12<avg_duration>s %12<min_duration>s %12<max_duration>s",
186
+ "\n%-6<method>s %-100<url>s %-6<requests>s %12<avg_duration>s %12<min_duration>s %12<max_duration>s",
178
187
  method: "Method",
179
188
  url: "URL",
180
189
  requests: "Requests",
@@ -188,6 +197,14 @@ module Lavin
188
197
  values.each_request { |request_values| puts yield request_values }
189
198
  puts divider
190
199
  end
200
+
201
+ def show_failures(values)
202
+ puts format("\n%-64<message>s %6<count>s", message: "Failures", count: "Count")
203
+ divider = "-" * 71
204
+ puts divider
205
+ values.each_failure { |failures| puts yield failures }
206
+ puts divider
207
+ end
191
208
  end
192
209
  end
193
210
  end
data/lib/lavin/stats.rb CHANGED
@@ -2,15 +2,16 @@
2
2
 
3
3
  module Lavin
4
4
  class Stats
5
- attr_reader :duration, :total_requests, :rate, :requests, :step_summary, :steps
5
+ attr_reader :duration, :total_requests, :rate, :requests, :step_summary, :steps, :failures
6
6
 
7
- def initialize(duration:, total_requests:, rate:, requests: [], step_summary: {}, steps: [])
7
+ def initialize(duration:, total_requests:, rate:, requests: [], step_summary: {}, steps: [], failures: [])
8
8
  @duration = duration
9
9
  @total_requests = total_requests
10
10
  @rate = rate
11
11
  @requests = requests
12
12
  @step_summary = step_summary
13
13
  @steps = steps
14
+ @failures = failures
14
15
  end
15
16
 
16
17
  def empty?
@@ -24,7 +25,8 @@ module Lavin
24
25
  rate:,
25
26
  requests:,
26
27
  step_summary:,
27
- steps:
28
+ steps:,
29
+ failures:
28
30
  }
29
31
  end
30
32
 
@@ -47,5 +49,9 @@ module Lavin
47
49
  def each_request(&block)
48
50
  requests.each(&block)
49
51
  end
52
+
53
+ def each_failure(&block)
54
+ failures.each(&block)
55
+ end
50
56
  end
51
57
  end
data/lib/lavin/step.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
- #
2
+
3
+ require 'lavin/error'
3
4
 
4
5
  module Lavin
5
6
  class Step
@@ -22,9 +23,10 @@ module Lavin
22
23
  def call(context:)
23
24
  context.instance_exec(&block)
24
25
  Statistics.register_step(user: user.name, step_name: name)
26
+ rescue IrrecoverableError => error
27
+ Statistics.register_step(user: user.name, step_name: name, failure: error.message)
28
+ throw :failure
25
29
  rescue => error
26
- puts "Caught an error - #{error.class}: #{error.message}"
27
- puts error.backtrace
28
30
  Statistics.register_step(user: user.name, step_name: name, failure: error.message)
29
31
  end
30
32
  end
data/lib/lavin/user.rb CHANGED
@@ -4,6 +4,7 @@ require "set"
4
4
  require "lavin/user_config"
5
5
  require "lavin/worker"
6
6
  require "lavin/http_client"
7
+ require "lavin/failure"
7
8
 
8
9
  module Lavin
9
10
  class User
@@ -12,6 +13,7 @@ module Lavin
12
13
  subclass.include UserConfig
13
14
  subclass.include Worker
14
15
  subclass.include HttpClient
16
+ subclass.include Failure
15
17
  all_personas << subclass
16
18
  end
17
19
 
data/lib/lavin/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lavin
4
- VERSION = "0.2.0"
4
+ VERSION = "0.3.0"
5
5
  end
@@ -40,6 +40,11 @@ module Lavin
40
40
  redirect to('/statistics')
41
41
  end
42
42
 
43
+ post '/stop' do
44
+ Lavin::Runner.stop
45
+ redirect to('/statistics')
46
+ end
47
+
43
48
  get '/statistics' do
44
49
  stats = Statistics.stats
45
50
  running = Lavin::Runner.running?
@@ -50,6 +55,16 @@ module Lavin
50
55
  end
51
56
  end
52
57
 
58
+ get '/failures' do
59
+ stats = Statistics.stats
60
+ running = Lavin::Runner.running?
61
+ if stats.empty? && !running
62
+ redirect to('/')
63
+ else
64
+ erb :failures, locals: {stats:, running:}
65
+ end
66
+ end
67
+
53
68
  get '/edit' do
54
69
  persona = find_persona
55
70
  raise Sinatra::NotFound unless persona
data/lib/lavin/worker.rb CHANGED
@@ -9,13 +9,13 @@ module Lavin
9
9
  def before(&block)
10
10
  return @before unless block
11
11
 
12
- @before = Hook.new(user: self, &block)
12
+ @before = Hook.new(user: self, type: :before, &block)
13
13
  end
14
14
 
15
15
  def after(&block)
16
16
  return @after unless block
17
17
 
18
- @after = Hook.new(user: self, &block)
18
+ @after = Hook.new(user: self, type: :after, &block)
19
19
  end
20
20
 
21
21
  def steps
@@ -40,11 +40,15 @@ module Lavin
40
40
  end
41
41
 
42
42
  def run
43
- self.class.before.run(context: self).then { Runner.yield } if self.class.before
43
+ catch(:failure) do
44
+ self.class.before.run(context: self).then { Runner.yield } if self.class.before
44
45
 
45
- run_step until finished?
46
+ run_step until finished?
47
+ end
46
48
 
47
- self.class.after.run(context: self).then { Runner.yield } if self.class.after
49
+ catch(:failure) do
50
+ self.class.after.run(context: self).then { Runner.yield } if self.class.after
51
+ end
48
52
  end
49
53
 
50
54
  private
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lavin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sammy Henningsson
@@ -29,7 +29,7 @@ cert_chain:
29
29
  DVzXaUnsmwP+jQ1PkDa5q8ibBzMd2c6Hmm87UDqPxZtML0bF9SjrpbyLMjwtXaMA
30
30
  WDPp0ajpdUZ9GPHsrVNYXiOfQIqcmlmpYVsH1o7vuneUIcIDMrnMDChh
31
31
  -----END CERTIFICATE-----
32
- date: 2022-10-31 00:00:00.000000000 Z
32
+ date: 2022-11-02 00:00:00.000000000 Z
33
33
  dependencies:
34
34
  - !ruby/object:Gem::Dependency
35
35
  name: async
@@ -113,6 +113,7 @@ files:
113
113
  - lib/lavin.rb
114
114
  - lib/lavin/client.rb
115
115
  - lib/lavin/error.rb
116
+ - lib/lavin/failure.rb
116
117
  - lib/lavin/hook.rb
117
118
  - lib/lavin/http_client.rb
118
119
  - lib/lavin/runner.rb
metadata.gz.sig CHANGED
Binary file