require "kemal" require "pg" require "commander" # Compose Objects (like Hash) to have a to_json method require "json/to_json" APPDB = DB.open(ENV["DATABASE_URL"]) class CONTENT UTF8 = "; charset=UTF-8" JSON = "application/json" PLAIN = "text/plain" HTML = "text/html" + UTF8 end ID_MAXIMUM = 10_000 private def random_world id = rand(1..ID_MAXIMUM) id, random_number = APPDB.query_one("SELECT id, randomNumber FROM world WHERE id = $1", id, as: {Int32, Int32}) {id: id, randomNumber: random_number} end private def set_world(world) APPDB.exec("UPDATE world SET randomNumber = $1 WHERE id = $2", world[:randomNumber], world[:id]) world end private def fortunes data = Array(NamedTuple(id: Int32, message: String)).new APPDB.query_each("SELECT id, message FROM Fortune") do |rs| data.push({id: rs.read(Int32), message: rs.read(String)}) end data end private def sanitized_query_count(request) queries = request.params.query["queries"]? || "1" queries = queries.to_i? || 1 queries.clamp(1..500) end private def sanitized_concurrency(request) concurrency = request.params.query["concurrency"]? || "1" concurrency.to_i? || 1 end before_all do |env| env.response.headers["Server"] = "Kemal" env.response.headers["Date"] = HTTP.format_time(Time.utc) end # # Basic Tests # # Test 1: JSON Serialization get "/json" do |env| env.response.content_type = CONTENT::JSON {message: "Hello, World!"}.to_json end # Test 6: Plaintext get "/plaintext" do |env| env.response.content_type = CONTENT::PLAIN "Hello, World!" end # # Postgres DatabaseTests # # Postgres Test 2: Single database query get "/db" do |env| env.response.content_type = CONTENT::JSON random_world.to_json end # Postgres Test 3: Multiple database query get "/queries" do |env| queries = sanitized_query_count(env) concurrency = sanitized_concurrency(env) results = if concurrency < 2 (1..queries).map do random_world end else cmd = Commander(NamedTuple(id: Int32, randomNumber: Int32)).new(queries, concurrency) queries.times do cmd.dispatch do random_world end end cmd.collect end env.response.content_type = CONTENT::JSON results.to_json end # Postgres Test 4: Fortunes get "/fortunes" do |env| env.response.content_type = CONTENT::HTML data = fortunes additional_fortune = { id: 0, message: "Additional fortune added at request time.", } data.push(additional_fortune) data.sort_by! { |fortune| fortune[:message] } render "views/fortunes.ecr" end # Postgres Test 5: Database Updates get "/updates" do |env| updated = (1..sanitized_query_count(env)).map do set_world({id: random_world[:id], randomNumber: rand(1..ID_MAXIMUM)}) end env.response.content_type = CONTENT::JSON updated.to_json end Kemal.config do |cfg| cfg.serve_static = false cfg.logging = false cfg.powered_by_header = false end Kemal.run { |cfg| cfg.server.not_nil!.bind_tcp(cfg.host_binding, cfg.port, reuse_port: true) }