startback 0.8.3 → 0.10.1
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 +4 -4
- data/lib/startback/audit/trailer.rb +4 -2
- data/lib/startback/bus/bunny/async.rb +8 -2
- data/lib/startback/errors.rb +15 -2
- data/lib/startback/operation/multi_operation.rb +1 -1
- data/lib/startback/operation.rb +1 -0
- data/lib/startback/support/log_formatter.rb +20 -6
- data/lib/startback/support/transaction_manager.rb +25 -0
- data/lib/startback/support/transaction_policy.rb +33 -0
- data/lib/startback/support.rb +2 -0
- data/lib/startback/version.rb +2 -2
- data/lib/startback/web/shield.rb +17 -2
- data/spec/unit/support/operation_runner/test_around_run.rb +3 -4
- data/spec/unit/support/test_transaction_manager.rb +64 -0
- metadata +12 -10
- data/VERSION +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ecd3fca505de294b037fbb0f7e15e9e5242823751169a8b745cd5717b9098945
|
4
|
+
data.tar.gz: d0b1546710de2899a9ea246b66a03661f58eea3ec03ba7d4f3c8e95c52d49245
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b0e1bde2cb31f15eeb777da14a9d22062f7dab45028d9de171c9de12526a4571296591eb208c4ebd6c1059730ef671ca76fea98553e7d618272244c2d4f8b7d3
|
7
|
+
data.tar.gz: 47a40ac9677ea5998c8089d6b5ca01b7ef7144810ecdde1163e6286fe41313d8009b723f52c074408aec6c316cacb978a6cfe9179f068ff4fe462e7647b75f8e
|
@@ -74,13 +74,13 @@ module Startback
|
|
74
74
|
|
75
75
|
protected
|
76
76
|
|
77
|
-
def op_to_trail(op, time, ex = nil)
|
77
|
+
def op_to_trail(op, time = nil, ex = nil)
|
78
78
|
log_msg = {
|
79
79
|
op_took: time ? time.round(8) : nil,
|
80
80
|
op: op_name(op),
|
81
81
|
context: op_context(op),
|
82
82
|
op_data: op_data(op)
|
83
|
-
}
|
83
|
+
}.compact
|
84
84
|
log_msg[:error] = ex if ex
|
85
85
|
log_msg
|
86
86
|
end
|
@@ -104,6 +104,8 @@ module Startback
|
|
104
104
|
op.input
|
105
105
|
elsif op.respond_to?(:request, false)
|
106
106
|
op.request
|
107
|
+
elsif op.is_a?(Operation::MultiOperation)
|
108
|
+
op.ops.map{ |sub_op| op_to_trail(sub_op) }
|
107
109
|
end
|
108
110
|
sanitize(data)
|
109
111
|
end
|
@@ -35,6 +35,8 @@ module Startback
|
|
35
35
|
class Async
|
36
36
|
include Support::Robustness
|
37
37
|
|
38
|
+
CHANNEL_KEY = 'Startback::Bus::Bunny::Async::ChannelKey'
|
39
|
+
|
38
40
|
DEFAULT_OPTIONS = {
|
39
41
|
# (optional) The URL to use for connecting to RabbitMQ.
|
40
42
|
url: ENV['STARTBACK_BUS_BUNNY_ASYNC_URL'],
|
@@ -65,11 +67,15 @@ module Startback
|
|
65
67
|
try_max_times(10) do
|
66
68
|
@bunny = ::Bunny.new(conn)
|
67
69
|
@bunny.start
|
68
|
-
|
70
|
+
channel
|
69
71
|
log(:info, {op: "#{self.class.name}#connect", op_data: conn}, options[:context])
|
70
72
|
end
|
71
73
|
end
|
72
|
-
attr_reader :
|
74
|
+
attr_reader :options
|
75
|
+
|
76
|
+
def channel
|
77
|
+
Thread.current[CHANNEL_KEY] ||= @bunny.create_channel
|
78
|
+
end
|
73
79
|
|
74
80
|
def emit(event)
|
75
81
|
stop_errors(self, "emit", event.context) do
|
data/lib/startback/errors.rb
CHANGED
@@ -2,8 +2,13 @@ module Startback
|
|
2
2
|
module Errors
|
3
3
|
|
4
4
|
class Error < StandardError
|
5
|
-
|
5
|
+
def initialize(message = nil, causes = nil)
|
6
|
+
super(message)
|
7
|
+
@causes = Array(causes)
|
8
|
+
end
|
9
|
+
attr_reader :causes
|
6
10
|
|
11
|
+
class << self
|
7
12
|
def status(code = nil)
|
8
13
|
if code.nil?
|
9
14
|
@code || (superclass.respond_to?(:status) ? superclass.status : 500)
|
@@ -22,11 +27,19 @@ module Startback
|
|
22
27
|
msg = super
|
23
28
|
return msg unless msg == self.class.name
|
24
29
|
parts = self.class.name.split('::').last.gsub(/[A-Z]/){|x|
|
25
|
-
" #{x.downcase}"
|
30
|
+
" #{x.downcase}"
|
26
31
|
}.strip.split(" ")
|
27
32
|
parts = parts[0...-1] unless self.class.keep_error
|
28
33
|
parts.join(" ").capitalize
|
29
34
|
end
|
35
|
+
|
36
|
+
def has_causes?
|
37
|
+
causes && !causes.empty?
|
38
|
+
end
|
39
|
+
|
40
|
+
def cause
|
41
|
+
causes&.first
|
42
|
+
end
|
30
43
|
end
|
31
44
|
|
32
45
|
class BadRequestError < Error
|
data/lib/startback/operation.rb
CHANGED
@@ -3,14 +3,28 @@ module Startback
|
|
3
3
|
class LogFormatter
|
4
4
|
|
5
5
|
def call(severity, time, progname, msg)
|
6
|
-
if msg[:error] && msg[:error].respond_to?(:message, true)
|
7
|
-
msg[:backtrace] = msg[:error].backtrace[0..25] if severity == "FATAL"
|
8
|
-
msg[:error] = msg[:error].message
|
9
|
-
end
|
10
6
|
{
|
11
7
|
severity: severity,
|
12
|
-
time: time
|
13
|
-
}.merge(msg)
|
8
|
+
time: time
|
9
|
+
}.merge(msg)
|
10
|
+
.merge(error: error_to_json(msg[:error], severity))
|
11
|
+
.compact
|
12
|
+
.to_json << "\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_to_json(error, severity = nil)
|
16
|
+
return error if error.nil?
|
17
|
+
return error if error.is_a?(String)
|
18
|
+
return error.to_s unless error.is_a?(Exception)
|
19
|
+
|
20
|
+
backtrace = error.backtrace[0..25] if severity == "FATAL"
|
21
|
+
causes = error.causes.map{|c| error_to_json(c) } if error.respond_to?(:causes)
|
22
|
+
causes = nil if causes && causes.empty?
|
23
|
+
{
|
24
|
+
message: error.message,
|
25
|
+
backtrace: backtrace,
|
26
|
+
causes: causes
|
27
|
+
}.compact
|
14
28
|
end
|
15
29
|
|
16
30
|
end # class LogFormatter
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Startback
|
2
|
+
module Support
|
3
|
+
class TransactionManager
|
4
|
+
|
5
|
+
def initialize(db, method = :transaction)
|
6
|
+
@db = db
|
7
|
+
@method = method
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(runner, op, &then_block)
|
11
|
+
raise ArgumentError, "A block is required" unless then_block
|
12
|
+
|
13
|
+
before = (op.class.transaction_policy == :before_call)
|
14
|
+
if before
|
15
|
+
@db.send(@method) do
|
16
|
+
then_block.call
|
17
|
+
end
|
18
|
+
else
|
19
|
+
then_block.call
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end # class TransactionManager
|
24
|
+
end # module Support
|
25
|
+
end # module Startback
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Startback
|
2
|
+
module Support
|
3
|
+
module TransactionPolicy
|
4
|
+
|
5
|
+
# Returns the operation's transaction policy
|
6
|
+
def transaction_policy
|
7
|
+
@transaction_policy || :before_call
|
8
|
+
end
|
9
|
+
|
10
|
+
# Sets the transaction policy to use. Valid values are:
|
11
|
+
# - before_call : the transaction is started by the operation
|
12
|
+
# runner, right before calling the #call method on operation
|
13
|
+
# instance
|
14
|
+
# - within_call: the transaction is started by the operation
|
15
|
+
# itself, as part of its internal logic.
|
16
|
+
def transaction_policy=(policy)
|
17
|
+
unless [:before_call, :within_call].include?(policy)
|
18
|
+
raise ArgumentError, "Unknown policy `#{policy}`"
|
19
|
+
end
|
20
|
+
@transaction_policy = policy
|
21
|
+
end
|
22
|
+
|
23
|
+
def after_commit(&bl)
|
24
|
+
after_call do
|
25
|
+
db.after_commit do
|
26
|
+
instance_exec(&bl)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end # module TransactionPolicy
|
32
|
+
end # module Support
|
33
|
+
end # module Startback
|
data/lib/startback/support.rb
CHANGED
data/lib/startback/version.rb
CHANGED
data/lib/startback/web/shield.rb
CHANGED
@@ -34,10 +34,25 @@ module Startback
|
|
34
34
|
# A bit of logic to choose the best error message for the user
|
35
35
|
# according to the error class
|
36
36
|
self.body{|ex|
|
37
|
-
ex
|
38
|
-
{ code: ex.class.name, description: ex.message }.to_json
|
37
|
+
body_for(ex).to_json
|
39
38
|
}
|
40
39
|
|
40
|
+
def body_for(ex)
|
41
|
+
ex = ex.root_cause if ex.is_a?(Finitio::TypeError)
|
42
|
+
body = { code: ex.class.name, description: ex.message }
|
43
|
+
return body unless ex.is_a?(Startback::Errors::Error)
|
44
|
+
return body unless ex.has_causes?
|
45
|
+
|
46
|
+
body[:causes] = ex.causes
|
47
|
+
.filter{|cause|
|
48
|
+
cause.is_a?(Startback::Errors::Error)
|
49
|
+
}
|
50
|
+
.map{|cause|
|
51
|
+
body_for(cause)
|
52
|
+
}
|
53
|
+
body
|
54
|
+
end
|
55
|
+
|
41
56
|
end # class Shield
|
42
57
|
end # module Web
|
43
58
|
end # module Startback
|
@@ -68,7 +68,7 @@ module Startback
|
|
68
68
|
end
|
69
69
|
|
70
70
|
context 'the around feature with a class' do
|
71
|
-
class
|
71
|
+
class SomeTransactionManager
|
72
72
|
include Singleton
|
73
73
|
|
74
74
|
def initialize
|
@@ -87,7 +87,7 @@ module Startback
|
|
87
87
|
|
88
88
|
class RunnerTest3
|
89
89
|
include OperationRunner
|
90
|
-
around_run
|
90
|
+
around_run SomeTransactionManager.instance
|
91
91
|
|
92
92
|
def operation_world(op)
|
93
93
|
{ hello: "world" }
|
@@ -97,7 +97,7 @@ module Startback
|
|
97
97
|
it 'calls the proc with expected parameters' do
|
98
98
|
test = RunnerTest3.new
|
99
99
|
got = test.run(op)
|
100
|
-
expect(
|
100
|
+
expect(SomeTransactionManager.instance.called).to eql(true)
|
101
101
|
expect(got).to eql({
|
102
102
|
seen_hello: "world"
|
103
103
|
})
|
@@ -154,4 +154,3 @@ module Startback
|
|
154
154
|
end # module OperationRunner
|
155
155
|
end # module Support
|
156
156
|
end # module Startback
|
157
|
-
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
module Startback
|
3
|
+
module Support
|
4
|
+
describe TransactionManager do
|
5
|
+
subject do
|
6
|
+
TransactionManager.new(db).call(nil, op) do
|
7
|
+
op.call
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FakeDatabase
|
12
|
+
def initialize
|
13
|
+
@called = false
|
14
|
+
end
|
15
|
+
attr_reader :called
|
16
|
+
|
17
|
+
def transaction
|
18
|
+
@called = true
|
19
|
+
yield
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:db) do
|
24
|
+
FakeDatabase.new
|
25
|
+
end
|
26
|
+
|
27
|
+
context 'when called with a default operation' do
|
28
|
+
class OperationNotManagingTransactions < Startback::Operation
|
29
|
+
def call
|
30
|
+
12
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:op) do
|
35
|
+
OperationNotManagingTransactions.new
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'calls db.transaction' do
|
39
|
+
expect(subject).to eql(12)
|
40
|
+
expect(db.called).to eql(true)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when called with an operation that manages the transactions itself' do
|
45
|
+
class OperationManagingTransactions < Startback::Operation
|
46
|
+
self.transaction_policy = :within_call
|
47
|
+
|
48
|
+
def call
|
49
|
+
12
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
let(:op) do
|
54
|
+
OperationManagingTransactions.new
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'calls db.transaction' do
|
58
|
+
expect(subject).to eql(12)
|
59
|
+
expect(db.called).to eql(false)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: startback
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bernard Lambeau
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-12-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -228,22 +228,22 @@ dependencies:
|
|
228
228
|
name: puma
|
229
229
|
requirement: !ruby/object:Gem::Requirement
|
230
230
|
requirements:
|
231
|
-
- - ">="
|
232
|
-
- !ruby/object:Gem::Version
|
233
|
-
version: 4.3.8
|
234
231
|
- - ">="
|
235
232
|
- !ruby/object:Gem::Version
|
236
233
|
version: 5.3.1
|
234
|
+
- - "<"
|
235
|
+
- !ruby/object:Gem::Version
|
236
|
+
version: '6.0'
|
237
237
|
type: :runtime
|
238
238
|
prerelease: false
|
239
239
|
version_requirements: !ruby/object:Gem::Requirement
|
240
240
|
requirements:
|
241
|
-
- - ">="
|
242
|
-
- !ruby/object:Gem::Version
|
243
|
-
version: 4.3.8
|
244
241
|
- - ">="
|
245
242
|
- !ruby/object:Gem::Version
|
246
243
|
version: 5.3.1
|
244
|
+
- - "<"
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: '6.0'
|
247
247
|
- !ruby/object:Gem::Dependency
|
248
248
|
name: jwt
|
249
249
|
requirement: !ruby/object:Gem::Requirement
|
@@ -380,7 +380,6 @@ extra_rdoc_files: []
|
|
380
380
|
files:
|
381
381
|
- README.md
|
382
382
|
- Rakefile
|
383
|
-
- VERSION
|
384
383
|
- lib/startback.rb
|
385
384
|
- lib/startback/audit.rb
|
386
385
|
- lib/startback/audit/prometheus.rb
|
@@ -411,6 +410,8 @@ files:
|
|
411
410
|
- lib/startback/support/logger.rb
|
412
411
|
- lib/startback/support/operation_runner.rb
|
413
412
|
- lib/startback/support/robustness.rb
|
413
|
+
- lib/startback/support/transaction_manager.rb
|
414
|
+
- lib/startback/support/transaction_policy.rb
|
414
415
|
- lib/startback/version.rb
|
415
416
|
- lib/startback/web/api.rb
|
416
417
|
- lib/startback/web/auto_caching.rb
|
@@ -438,6 +439,7 @@ files:
|
|
438
439
|
- spec/unit/support/operation_runner/test_around_run.rb
|
439
440
|
- spec/unit/support/operation_runner/test_before_after_call.rb
|
440
441
|
- spec/unit/support/test_robusteness.rb
|
442
|
+
- spec/unit/support/test_transaction_manager.rb
|
441
443
|
- spec/unit/test_event.rb
|
442
444
|
- spec/unit/test_operation.rb
|
443
445
|
- spec/unit/test_support.rb
|
@@ -470,7 +472,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
470
472
|
- !ruby/object:Gem::Version
|
471
473
|
version: '0'
|
472
474
|
requirements: []
|
473
|
-
rubygems_version: 3.2.
|
475
|
+
rubygems_version: 3.2.32
|
474
476
|
signing_key:
|
475
477
|
specification_version: 4
|
476
478
|
summary: Got Your Ruby Back
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.8.3
|