hello_world.rb 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. # frozen_string_literal: true
  2. # Our Rack application to be executed by rackup
  3. class HelloWorld
  4. DEFAULT_HEADERS = {}.tap do |h|
  5. h['Server'] = SERVER_STRING if SERVER_STRING
  6. end.freeze
  7. def bounded_queries(env)
  8. params = Rack::Utils.parse_query(env['QUERY_STRING'])
  9. queries = params['queries'].to_i
  10. return QUERIES_MIN if queries < QUERIES_MIN
  11. return QUERIES_MAX if queries > QUERIES_MAX
  12. queries
  13. end
  14. # Return a random number between 1 and MAX_PK
  15. def rand1
  16. Random.rand(MAX_PK).succ
  17. end
  18. # Return an array of `n' unique random numbers between 1 and MAX_PK
  19. def randn(n)
  20. (1..MAX_PK).to_a.shuffle!.take(n)
  21. end
  22. def db
  23. World.with_pk(rand1).values
  24. end
  25. def queries(env)
  26. # Benchmark requirements explicitly forbid a WHERE..IN here, so be good
  27. randn(bounded_queries(env))
  28. .map! { |id| World.with_pk(id).values }
  29. end
  30. def fortunes
  31. fortunes = Fortune.all
  32. fortunes << Fortune.new(
  33. :id=>0,
  34. :message=>'Additional fortune added at request time.'
  35. )
  36. fortunes.sort_by!(&:message)
  37. html = <<~'HTML'
  38. <!DOCTYPE html>
  39. <html>
  40. <head>
  41. <title>Fortunes</title>
  42. </head>
  43. <body>
  44. <table>
  45. <tr>
  46. <th>id</th>
  47. <th>message</th>
  48. </tr>
  49. HTML
  50. fortunes.each do |fortune|
  51. html += <<~"HTML"
  52. <tr>
  53. <td>#{Rack::Utils.escape_html(fortune.id)}</td>
  54. <td>#{Rack::Utils.escape_html(fortune.message)}</td>
  55. </tr>
  56. HTML
  57. end
  58. html += <<~'HTML'
  59. </table>
  60. </body>
  61. </html>
  62. HTML
  63. end
  64. WORLD_BY_ID_FOR_UPDATE = World.naked.for_update.where(:id=>:$id).prepare(:first, :world_by_id_for_update)
  65. WORLD_UPDATE = World.where(:id=>:$id).prepare(:update, :world_update, :randomnumber=>:$randomnumber)
  66. def updates(env)
  67. # Benchmark requirements explicitly forbid a WHERE..IN here, transactions
  68. # are optional, batch updates are allowed (but each transaction can only
  69. # read and write a single record?), so... be good
  70. randn(bounded_queries(env)).map! do |id|
  71. DB.transaction do
  72. world = WORLD_BY_ID_FOR_UPDATE.(:id=>id)
  73. WORLD_UPDATE.(:id=>id, :randomnumber=>(world[:randomnumber] = rand1))
  74. world
  75. end
  76. end
  77. end
  78. def call(env)
  79. content_type, *body =
  80. case env['PATH_INFO']
  81. when '/json'
  82. # Test type 1: JSON serialization
  83. ['application/json', JSON.fast_generate(:message=>'Hello, World!')]
  84. when '/db'
  85. # Test type 2: Single database query
  86. ['application/json', JSON.fast_generate(db)]
  87. when '/queries'
  88. # Test type 3: Multiple database queries
  89. ['application/json', JSON.fast_generate(queries(env))]
  90. when '/fortunes'
  91. # Test type 4: Fortunes
  92. ['text/html; charset=utf-8', fortunes]
  93. when '/updates'
  94. # Test type 5: Database updates
  95. ['application/json', JSON.fast_generate(updates(env))]
  96. when '/plaintext'
  97. # Test type 6: Plaintext
  98. ['text/plain', 'Hello, World!']
  99. end
  100. return 200,
  101. DEFAULT_HEADERS.merge(
  102. 'Content-Type'=>content_type,
  103. 'Date'=>Time.now.httpdate
  104. ),
  105. body
  106. end
  107. end