-
Notifications
You must be signed in to change notification settings - Fork 1
/
benchmark_helper.rb
182 lines (161 loc) · 4.71 KB
/
benchmark_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
if ENV['DYNFLOW_PATH']
$:.unshift(ENV['DYNFLOW_PATH'])
elsif File.exists?('./lib/dynflow.rb')
$:.unshift('./lib')
end
begin
require 'dynflow'
require 'dynflow/version'
rescue LoadError => e
puts e
puts <<EOF
Dynflow source code not present. Install the version of Dynflow you want
to benchmark, set DYNFLOW_PATH to the path where the source is located or
run the executable from the Dynflow directory.
On Foreman system, you might want to run
scl enable tfm bash
EOF
end
module LoggerHelper
def logger
@__logger ||= Logger.new(STDERR).tap do |logger|
if $DYNFLOW_BENCHMARK_VERBOSE
logger.level = Logger::DEBUG
else
logger.level = Logger::INFO
end
logger.formatter = proc do |severity, datetime, progname, msg|
s = severity[0...1]
date_format = datetime.strftime("%H:%M:%S")
"#{s} [#{date_format}]: #{msg}\n"
end
end
end
end
class BenchmarkHelper
class << self
include LoggerHelper
def set_world(world)
@world = world
if @terminate && [email protected]?
logger.debug "Terminating world #{@world.id}"
@world.terminate.wait
logger.debug "World #{@world.id} termination finished"
end
end
def with_client
client = create_client
yield client
ensure
client.terminate.wait(5) if client
end
def ensure_db_prepared
with_client do |client|
if Gem::Version.new(Dynflow::VERSION) >= Gem::Version.new('1.1')
client.perform_validity_checks
end
end
end
def create_world
config = Dynflow::Config.new
config.persistence_adapter = persistence_adapter
config.logger_adapter = logger_adapter
config.auto_rescue = false
config.auto_execute = false
if Gem::Version.new(Dynflow::VERSION) >= Gem::Version.new('1.1')
config.telemetry_adapter = telemetry_adapter
end
yield config if block_given?
Dynflow::World.new(config)
end
def telemetry_adapter
if (host = ENV['TELEMETRY_STATSD_HOST'])
Dynflow::TelemetryAdapters::StatsD.new host
else
Dynflow::TelemetryAdapters::Dummy.new
end
end
def logger_adapter
Dynflow::LoggerAdapters::Simple.new $stderr, $DYNFLOW_BENCHMARK_VERBOSE ? 1 : 4
end
def run_web_console(world)
require 'dynflow/web'
dynflow_console = Dynflow::Web.setup do
set :world, world
end
require 'webrick'
logger = Logger.new(STDERR)
logger.level = Logger::ERROR
@console = ::WEBrick::HTTPServer.new(:Logger => logger, :Port => 4567)
@console.mount "/", Rack::Handler::WEBrick, dynflow_console
@console.start
end
def terminate
if @console
logger.debug "Terminating http console"
@console.shutdown
@console = nil
end
if @world
logger.debug "Terminating world #{@world.id}"
@world.terminate.wait
logger.debug "World #{@world.id} termination finished"
else
unless @terminate
logger.debug "World not present, triggering delayed termination"
@terminate = true
end
end
end
def run_observer
world = create_world do |config|
config.persistence_adapter = persistence_adapter
config.connector = connector
config.executor = false
end
set_world(world)
logger.debug "Observer #{world.id} started"
puts "The console is available at http://localhost:4567"
run_web_console(world)
end
def run_executor
world = create_world do |config|
config.persistence_adapter = persistence_adapter
config.connector = connector
end
set_world(world)
logger.info "Executor #{world.id} started"
world.terminated.wait
end
def create_client
create_world do |config|
config.persistence_adapter = persistence_adapter
config.executor = false
config.connector = connector
config.exit_on_terminate = false
end
end
def db_path
File.expand_path("../remote_executor_db.sqlite", __FILE__)
end
def persistence_conn_string
ENV['DB_CONN_STRING'] || "sqlite://#{db_path}"
end
def persistence_adapter
Dynflow::PersistenceAdapters::Sequel.new persistence_conn_string
end
def connector
Proc.new { |world| Dynflow::Connectors::Database.new(world) }
end
end
end
at_exit { BenchmarkHelper.terminate }
trap(:INT) do
# for cases the happy path doesn't work well
if $already_interrupted
Thread.new { Kernel.exit }
else
$already_interrupted = true
Thread.new { BenchmarkHelper.terminate }
end
end