server-postgres.cr 3.3 KB

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