Browse Source

add moonshine crystal postgres

Keenan Brock 9 years ago
parent
commit
2e18f3bef4

+ 24 - 1
frameworks/Crystal/moonshine/benchmark_config.json

@@ -23,6 +23,29 @@
       "display_name": "Moonshine",
       "display_name": "Moonshine",
       "notes": "",
       "notes": "",
       "versus": "ruby"
       "versus": "ruby"
+    },
+    "postgres": {
+      "setup_file": "setup-postgres",
+      "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
+      "plaintext_url": "/plaintext",
+      "port": 8080,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "moonshine",
+      "language": "Crystal",
+      "orm": "micro",
+      "platform": "Crystal",
+      "webserver": "None",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Moonshine",
+      "notes": "",
+      "versus": "ruby"
     }
     }
   }]
   }]
-}
+}

+ 158 - 0
frameworks/Crystal/moonshine/server-postgres.cr

@@ -0,0 +1,158 @@
+require "moonshine"
+require "pg"
+require "html/builder"
+
+include Moonshine
+include Moonshine::Utils::Shortcuts
+include Moonshine::Base
+
+# Compose Objects (like Hash) to have a to_json method
+require "json/to_json"
+
+DB = PG.connect("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
+app = App.new
+
+class CONTENT
+  UTF8 = "; charset=UTF-8"
+  JSON = "application/json" + UTF8
+  PLAIN = "text/plain"
+  HTML = "text/html" + UTF8
+end
+
+ID_MAXIMUM = 10_000
+
+app.response_middleware do |req, res|
+    res.headers["Server"] = "Moonshine"
+    res.headers["Date"] = Time.now.to_s
+    res
+end
+
+private def randomWorld
+  id = rand(1..ID_MAXIMUM)
+  result = DB.exec({Int32, Int32}, "SELECT id, randomNumber FROM world WHERE id = $1", [id]).rows.first
+  {:id => result[0], :randomNumber => result[1]}
+end
+
+private def setWorld(world)
+  DB.exec("UPDATE world set randomNumber = $1 where id = $2", [world[:randomNumber], world[:id]])
+  world
+end
+
+private def fortunes
+  data = [] of  Hash(Symbol, (String | Int32))
+
+  DB.exec({Int32, String}, "select id, message from Fortune").rows.each do |row|
+    data.push({:id => row[0], :message => row[1]})
+  end
+  data
+end
+
+private def sanitizedQueryCount(request)
+  begin
+    queries = request.get["queries"].to_i
+  rescue
+    queries = 1
+  end
+  queries = 1 if queries < 1
+  queries = 500 if queries > 500
+  queries
+end
+
+#
+# Basic Tests
+#
+
+# Test 1: JSON Serialization
+app.get "/json", do |request|
+  res = ok({ :message => "Hello, World!" }.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Test 6: Plaintext
+app.get "/plaintext", do |request|
+  res = ok("Hello, World!")
+  res.headers["Content-type"] = CONTENT::PLAIN
+  res
+end
+
+#
+# Postgres DatabaseTests
+#
+
+# Postgres Test 2: Single database query
+app.get "/db", do |request|
+  res = ok(randomWorld.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Postgres Test 3: Multiple database query
+app.get "/queries", do |request|
+  results = (1..sanitizedQueryCount(request)).map do
+    randomWorld
+  end
+
+  res = ok(results.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+# Postgres Test 4: Fortunes
+app.get "/fortunes", do |request|
+  data = fortunes
+  
+  additional_fortune = {
+    :id => 0,
+    :message => "Additional fortune added at request time."
+  }
+  data.push(additional_fortune)
+
+  data.sort! do |a, b|
+    a[:message].to_s <=> b[:message].to_s
+  end
+
+  # New builder for each request!
+  html = HTML::Builder.new.build do
+    html {
+      head {
+        title { text "Fortunes" }
+      }
+      body {
+        table {
+          tr {
+            thead { text "id" }
+            thead { text "message" }
+          }
+          data.each { |e|
+            tr {
+              td { text e[:id].to_s }
+              td { text e[:message].to_s }
+            }
+          }
+        }
+      }
+    }
+  end
+
+  # Doctype not available in builder
+  # builder only supports `thead`, tests need to see `th`
+  res = ok("<!doctype html>" + html.gsub("thead", "th"))
+  res.headers["Content-type"] = CONTENT::HTML
+  res
+end
+
+# Postgres Test 5: Database Updates
+app.get "/updates", do |request|
+  updated = (1..sanitizedQueryCount(request)).map do
+    world = randomWorld
+    world[:randomNumber] = rand(1..ID_MAXIMUM)
+    setWorld(world)
+  end
+
+  res = ok(updated.to_json)
+  res.headers["Content-type"] = CONTENT::JSON
+  res
+end
+
+app.run(8080)

+ 7 - 0
frameworks/Crystal/moonshine/setup-postgres.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+fw_depends crystal
+
+crystal deps install
+
+crystal server-postgres.cr &