-
Notifications
You must be signed in to change notification settings - Fork 0
/
app.rb
160 lines (128 loc) · 3.68 KB
/
app.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
require 'sinatra/base'
require_relative 'routes/init'
require_relative 'models/init'
require_relative 'lib/log_wrapper'
require 'uri'
require 'redis'
require 'json'
require 'ohm'
require 'celluloid'
require 'log4r'
require 'log4r/yamlconfigurator'
require 'log4r/outputter/datefileoutputter'
class TranscoderManager < Sinatra::Base
# initialize logging
disable :logging
Log4r::YamlConfigurator.load_yaml_file "#{File.dirname(__FILE__)}/config/logging-#{ENV['RACK_ENV']}.yml"
use Rack::CommonLogger, LogWrapper.new('main')
Log4r::Logger['main'].debug('Application loaded')
# initialize connection to redis
set :redis_url, ENV['REDIS_URL'] || 'redis://127.0.0.1/0'
Ohm.connect url: settings.redis_url, driver: :hiredis
Ohm.redis.ping
# initialize monitoring
MonitorService.instance.start if 'production' == ENV['RACK_ENV']
# configure sinatra
configure do
set :app_file, __FILE__
disable :show_exceptions
disable :raise_errors
set :protection, :except => :json_csrf
end
configure :development do
enable :dump_errors
end
configure :test do
enable :dump_errors
enable :raise_errors
end
configure :production do
disable :dump_errors
end
# General routes
before do
content_type :json
# allow cross origin calls
headers 'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST, GET, OPTIONS',
'Access-Control-Allow-Headers' => 'Content-Type'
# normalize base path from custom header
base_path = env['HTTP_X_FORWARDED_BASE_PATH'] || '/'
base_path = '' if base_path == '/'
env['PATH_INFO'][base_path]= ''
end
get '/' do
halt 200,
{'Content-Type' => 'text/plain'},
"BB Web Broadcast - Transcoder Manager. #{Time.now}"
end
get '/test-redis' do
msg = 'redis is dead.'
if Ohm.redis.ping == 'PONG'
msg = "redis is alive at #{Ohm.conn.options[:url]}".to_json
end
halt 200, {'Content-Type' => 'text/plain'}, msg
end
# Error handlers
class ApiError < StandardError; end
class MissingModelError < StandardError; end
not_found do
'This is nowhere to be found. Intention !'
end
error do
e = env['sinatra.error']
if e.message =~ /reconnect to Redis/
logger.warn "Redis connection error: #{e.message}. Trying to reconnect."
recover_redis_connection
else
handle_error 500, 'Internal Server Error'
end
end
error ApiError do
handle_error 500, 'Api error'
end
error Transcoder::TranscoderError do
handle_error 500, 'Transcoder error'
end
error ArgumentError do
handle_error 400, 'Argument error'
end
error MissingModelError do
halt 404
end
private
def logger
logger = Log4r::Logger['main']
raise 'logging not initialized properly' if logger.nil?
logger
end
def log_exception(e)
trace = e.backtrace.join("\n")
logger.error("Exception: '#{e.message}'\nBacktrace:\n#{trace}")
end
def success(msg = 'success')
{result: msg}.to_json
end
def handle_error(status, message)
e = env['sinatra.error']
status == 500 ? log_exception(e) : logger.warn(e.message)
halt status, {'Content-Type' => 'text/plain'}, "#{message} - #{e.message}"
end
def expect_params(*parameter_names)
parameter_names.map do |p|
raise ArgumentError, "expecting #{p} but didn't get any" unless params[p]
params[p]
end
end
def recover_redis_connection
begin
Ohm.connect url: settings.redis_url, driver: :hiredis
if Ohm.redis.ping == 'PONG'
logger.info 'Successfully reconnected to redis. Re invoking route'
dispatch!
end
rescue => ex
logger.error "Unable to reconnect: #{ex.message}"
end
end
end