app.rb 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. # frozen_string_literal: true
  2. require 'agoo'
  3. require 'connection_pool'
  4. require 'oj'
  5. require 'pg'
  6. require 'rack'
  7. $pool = ConnectionPool.new(size: 256, timeout: 5) do
  8. PG::Connection.new({
  9. dbname: 'hello_world',
  10. host: 'tfb-database',
  11. user: 'benchmarkdbuser',
  12. password: 'benchmarkdbpass'
  13. })
  14. end
  15. class BaseHandler
  16. def self.extract_queries_param(request = nil)
  17. queries = Rack::Utils.parse_query(request['QUERY_STRING'])['queries'].to_i rescue 1
  18. return 1 if queries < 1
  19. return 500 if queries > 500
  20. queries
  21. end
  22. def self.get_one_random_number
  23. 1 + Random.rand(10000)
  24. end
  25. def self.get_one_record(id = get_one_random_number)
  26. $pool.with do |conn|
  27. conn.exec_params(<<-SQL, [id]).first
  28. SELECT * FROM world WHERE id = $1
  29. SQL
  30. end
  31. end
  32. def self.html_response(str = '')
  33. [
  34. 200,
  35. {
  36. 'Content-Type' => 'text/html; charset=utf-8',
  37. 'Date' => Time.now.utc.httpdate,
  38. 'Server' => 'Agoo'
  39. },
  40. [str]
  41. ]
  42. end
  43. def self.json_response(obj = {})
  44. [
  45. 200,
  46. {
  47. 'Content-Type' => 'application/json',
  48. 'Date' => Time.now.utc.httpdate,
  49. 'Server' => 'Agoo'
  50. },
  51. [Oj.dump(obj, { :mode => :strict })]
  52. ]
  53. end
  54. def self.plain_response(str = '')
  55. [
  56. 200,
  57. {
  58. 'Content-Type' => 'text/plain',
  59. 'Date' => Time.now.utc.httpdate,
  60. 'Server' => 'Agoo'
  61. },
  62. [str]
  63. ]
  64. end
  65. end
  66. class PlaintextHandler < BaseHandler
  67. def self.call(_req)
  68. plain_response('Hello, World!')
  69. end
  70. def static?
  71. true
  72. end
  73. end
  74. class JsonHandler < BaseHandler
  75. def self.call(_req)
  76. json_response({ :message => "Hello, World!" })
  77. end
  78. def static?
  79. true
  80. end
  81. end
  82. class DbHandler < BaseHandler
  83. def self.call(_req)
  84. json_response(get_one_record)
  85. end
  86. end
  87. class FortunesHandler < BaseHandler
  88. def self.call(_req)
  89. f_1 = $pool.with do |conn|
  90. conn.exec(<<-SQL)
  91. SELECT id, message FROM fortune
  92. SQL
  93. end
  94. f_2 = f_1.map(&:to_h).
  95. append({ 'id' => '0', 'message' => 'Additional fortune added at request time.' }).
  96. sort { |x,y| x['message'] <=> y['message'] }.
  97. map { |f| "<tr><td>#{ f['id'] }</td><td>#{ Rack::Utils.escape_html(f['message']) }</td></tr>" }.
  98. join
  99. html_response(<<-HTML)
  100. <!DOCTYPE html>
  101. <html>
  102. <head>
  103. <title>Fortune</title>
  104. </head>
  105. <body>
  106. <table>
  107. <tr>
  108. <th>id</th>
  109. <th>message</th>
  110. </tr>
  111. #{ f_2 }
  112. </table>
  113. </body
  114. </html>
  115. HTML
  116. end
  117. end
  118. class QueriesHandler < BaseHandler
  119. def self.call(req)
  120. records =
  121. [].tap do|r|
  122. (extract_queries_param req).times do
  123. r << get_one_record()
  124. end
  125. end
  126. json_response(records)
  127. end
  128. end
  129. class UpdatesHandler < BaseHandler
  130. def self.call(req)
  131. records =
  132. [].tap do|r|
  133. (extract_queries_param req).times do
  134. r << get_one_record()
  135. end
  136. end
  137. updated_records =
  138. records.map { |r| r['randomnumber'] = get_one_random_number; r }
  139. sql_values =
  140. updated_records.
  141. map { |r| "(#{ r['id'] }, #{ r['randomnumber'] })"}.
  142. join(', ')
  143. $pool.with do |conn|
  144. conn.exec(<<-SQL)
  145. UPDATE world AS ori
  146. SET randomnumber = new.randomnumber
  147. FROM (VALUES #{ sql_values }) AS new (id, randomnumber)
  148. WHERE ori.id = new.id
  149. SQL
  150. end
  151. json_response(updated_records)
  152. end
  153. end
  154. Agoo::Log.configure({
  155. classic: true,
  156. colorize: true,
  157. console: true,
  158. dir: '',
  159. states: {
  160. DEBUG: false,
  161. INFO: false,
  162. connect: false,
  163. eval: false,
  164. push: false,
  165. request: false,
  166. response: false
  167. }
  168. })
  169. worker_count = 4
  170. worker_count = ENV['AGOO_WORKER_COUNT'].to_i if ENV.key?('AGOO_WORKER_COUNT')
  171. Agoo::Server.init(8080, '.', thread_count: 0, worker_count: worker_count)
  172. Agoo::Server.handle(:GET, '/plaintext', PlaintextHandler)
  173. Agoo::Server.handle(:GET, '/json', JsonHandler)
  174. Agoo::Server.handle(:GET, '/db', DbHandler)
  175. Agoo::Server.handle(:GET, '/fortunes', FortunesHandler)
  176. Agoo::Server.handle(:GET, '/queries', QueriesHandler)
  177. Agoo::Server.handle(:GET, '/updates', UpdatesHandler)
  178. Agoo::Server.start