server-postgres.cr 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. require "moonshine"
  2. require "pg"
  3. require "html/builder"
  4. include Moonshine
  5. include Moonshine::Utils::Shortcuts
  6. # Compose Objects (like Hash) to have a to_json method
  7. require "json/to_json"
  8. DB = PG.connect("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
  9. app = App.new
  10. class CONTENT
  11. UTF8 = "; charset=UTF-8"
  12. JSON = "application/json" + UTF8
  13. PLAIN = "text/plain"
  14. HTML = "text/html" + UTF8
  15. end
  16. ID_MAXIMUM = 10_000
  17. app.response_middleware do |req, res|
  18. res.headers["Server"] = "Moonshine"
  19. res.headers["Date"] = Time.now.to_s
  20. res
  21. end
  22. private def randomWorld
  23. id = rand(1..ID_MAXIMUM)
  24. result = DB.exec({Int32, Int32}, "SELECT id, randomNumber FROM world WHERE id = $1", [id]).rows.first
  25. {:id => result[0], :randomNumber => result[1]}
  26. end
  27. private def setWorld(world)
  28. DB.exec("UPDATE world set randomNumber = $1 where id = $2", [world[:randomNumber], world[:id]])
  29. world
  30. end
  31. private def fortunes
  32. data = [] of Hash(Symbol, (String | Int32))
  33. DB.exec({Int32, String}, "select id, message from Fortune").rows.each do |row|
  34. data.push({:id => row[0], :message => row[1]})
  35. end
  36. data
  37. end
  38. private def sanitizedQueryCount(request)
  39. begin
  40. queries = request.get["queries"].to_i
  41. rescue
  42. queries = 1
  43. end
  44. queries = 1 if queries < 1
  45. queries = 500 if queries > 500
  46. queries
  47. end
  48. #
  49. # Basic Tests
  50. #
  51. # Test 1: JSON Serialization
  52. app.get "/json", do |request|
  53. res = ok({ :message => "Hello, World!" }.to_json)
  54. res.headers["Content-type"] = CONTENT::JSON
  55. res
  56. end
  57. # Test 6: Plaintext
  58. app.get "/plaintext", do |request|
  59. res = ok("Hello, World!")
  60. res.headers["Content-type"] = CONTENT::PLAIN
  61. res
  62. end
  63. #
  64. # Postgres DatabaseTests
  65. #
  66. # Postgres Test 2: Single database query
  67. app.get "/db", do |request|
  68. res = ok(randomWorld.to_json)
  69. res.headers["Content-type"] = CONTENT::JSON
  70. res
  71. end
  72. # Postgres Test 3: Multiple database query
  73. app.get "/queries", do |request|
  74. results = (1..sanitizedQueryCount(request)).map do
  75. randomWorld
  76. end
  77. res = ok(results.to_json)
  78. res.headers["Content-type"] = CONTENT::JSON
  79. res
  80. end
  81. # Postgres Test 4: Fortunes
  82. app.get "/fortunes", do |request|
  83. data = fortunes
  84. additional_fortune = {
  85. :id => 0,
  86. :message => "Additional fortune added at request time."
  87. }
  88. data.push(additional_fortune)
  89. data.sort! do |a, b|
  90. a[:message].to_s <=> b[:message].to_s
  91. end
  92. # New builder for each request!
  93. html = HTML::Builder.new.build do
  94. html {
  95. head {
  96. title { text "Fortunes" }
  97. }
  98. body {
  99. table {
  100. tr {
  101. thead { text "id" }
  102. thead { text "message" }
  103. }
  104. data.each { |e|
  105. tr {
  106. td { text e[:id].to_s }
  107. td { text e[:message].to_s }
  108. }
  109. }
  110. }
  111. }
  112. }
  113. end
  114. # Doctype not available in builder
  115. # builder only supports `thead`, tests need to see `th`
  116. res = ok("<!doctype html>" + html.gsub("thead", "th"))
  117. res.headers["Content-type"] = CONTENT::HTML
  118. res
  119. end
  120. # Postgres Test 5: Database Updates
  121. app.get "/updates", do |request|
  122. updated = (1..sanitizedQueryCount(request)).map do
  123. world = randomWorld
  124. world[:randomNumber] = rand(1..ID_MAXIMUM)
  125. setWorld(world)
  126. end
  127. res = ok(updated.to_json)
  128. res.headers["Content-type"] = CONTENT::JSON
  129. res
  130. end
  131. app.run(8080)