server-postgres.cr 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. require "kemal"
  2. require "pg"
  3. require "pool/connection"
  4. require "html_builder"
  5. # Compose Objects (like Hash) to have a to_json method
  6. require "json/to_json"
  7. DB = ConnectionPool.new(capacity: 25, timeout: 0.01) do
  8. PG.connect("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
  9. end
  10. class CONTENT
  11. UTF8 = "; charset=UTF-8"
  12. JSON = "application/json"
  13. PLAIN = "text/plain"
  14. HTML = "text/html" + UTF8
  15. end
  16. ID_MAXIMUM = 10_000
  17. private def random_world
  18. id = rand(1..ID_MAXIMUM)
  19. conn = DB.checkout
  20. result = conn.exec({Int32, Int32}, "SELECT id, randomNumber FROM world WHERE id = $1", [id]).rows.first
  21. DB.checkin(conn)
  22. {id: result[0], randomNumber: result[1]}
  23. end
  24. private def set_world(world)
  25. conn = DB.checkout
  26. result = conn.exec("UPDATE world set randomNumber = $1 where id = $2", [world[:randomNumber], world[:id]])
  27. DB.checkin(conn)
  28. world
  29. end
  30. private def fortunes
  31. data = [] of NamedTuple(id: Int32, message: String)
  32. DB.connection.exec({Int32, String}, "select id, message from Fortune").rows.each do |row|
  33. data.push({id: row[0], message: row[1]})
  34. end
  35. data
  36. end
  37. private def sanitized_query_count(request)
  38. queries = request.params.query["queries"].as(String)
  39. queries = queries.to_i? || 1
  40. queries.clamp(1..500)
  41. end
  42. before_all do |env|
  43. env.response.headers["Server"] = "Kemal"
  44. env.response.headers["Date"] = Time.now.to_s
  45. end
  46. #
  47. # Basic Tests
  48. #
  49. # Test 1: JSON Serialization
  50. get "/json" do |env|
  51. env.response.content_type = CONTENT::JSON
  52. {message: "Hello, World!"}.to_json
  53. end
  54. # Test 6: Plaintext
  55. get "/plaintext" do |env|
  56. env.response.content_type = CONTENT::PLAIN
  57. "Hello, World!"
  58. end
  59. #
  60. # Postgres DatabaseTests
  61. #
  62. # Postgres Test 2: Single database query
  63. get "/db" do |env|
  64. env.response.content_type = CONTENT::JSON
  65. random_world.to_json
  66. end
  67. # Postgres Test 3: Multiple database query
  68. get "/queries" do |env|
  69. results = (1..sanitized_query_count(env)).map do
  70. random_world
  71. end
  72. env.response.content_type = CONTENT::JSON
  73. results.to_json
  74. end
  75. # Postgres Test 4: Fortunes
  76. get "/fortunes" do |env|
  77. data = fortunes
  78. additional_fortune = {
  79. id: 0,
  80. message: "Additional fortune added at request time.",
  81. }
  82. data.push(additional_fortune)
  83. data.sort_by! {|fortune| fortune[:message] }
  84. env.response.content_type = CONTENT::HTML
  85. # New builder for each request!
  86. HTML::Builder.new.build do
  87. doctype
  88. html {
  89. head {
  90. title { html "Fortunes" }
  91. }
  92. body {
  93. table {
  94. tr {
  95. th { html "id" }
  96. th { html "message" }
  97. }
  98. data.each { |e|
  99. tr {
  100. td { html e[:id] }
  101. td { text e[:message] }
  102. }
  103. }
  104. }
  105. }
  106. }
  107. end
  108. end
  109. # Postgres Test 5: Database Updates
  110. get "/updates" do |env|
  111. updated = (1..sanitized_query_count(env)).map do
  112. set_world({id: random_world[:id], randomNumber: rand(1..ID_MAXIMUM)})
  113. end
  114. env.response.content_type = CONTENT::JSON
  115. updated.to_json
  116. end
  117. Kemal.run