Explorar o código

Added DB endpoints to crystal-raw (#2894)

* Added implementations for DB tests.

* Updated to use more efficient JSON building & sorting methods.

* Code cleanup

* Used times instead of upto.
foliot %!s(int64=8) %!d(string=hai) anos
pai
achega
686ede4040

+ 4 - 0
frameworks/Crystal/crystal/.gitignore

@@ -0,0 +1,4 @@
+lib/
+.crystal
+.shards
+!shard.lock

+ 4 - 0
frameworks/Crystal/crystal/benchmark_config.json

@@ -4,6 +4,10 @@
     "default": {
       "setup_file": "setup",
       "json_url": "/json",
+      "db_url": "/db",
+      "query_url": "/queries?queries=",
+      "fortune_url": "/fortunes",
+      "update_url": "/updates?queries=",
       "plaintext_url": "/plaintext",
       "port": 8080,
       "approach": "Realistic",

+ 78 - 2
frameworks/Crystal/crystal/server.cr

@@ -1,11 +1,19 @@
 require "http/server"
 require "json"
+require "pg"
+require "ecr"
+
+APPDB = DB.open("postgres://benchmarkdbuser:benchmarkdbpass@#{ENV["DBHOST"]? || "127.0.0.1"}/hello_world")
+ID_MAXIMUM = 10_000
 
 server = HTTP::Server.new("0.0.0.0", 8080) do |context|
   response = context.response
+  request = context.request
+
   response.headers["Server"] = "Crystal"
   response.headers["Date"] = Time.utc_now.to_s
-  case context.request.path
+  
+  case request.path
   when "/json"
     response.status_code = 200
     response.headers["Content-Type"] = "application/json"
@@ -14,9 +22,77 @@ server = HTTP::Server.new("0.0.0.0", 8080) do |context|
     response.status_code = 200
     response.headers["Content-Type"] = "text/plain"
     response.print "Hello, World!"
+  when "/db"
+    response.status_code = 200
+    response.headers["Content-Type"] = "application/json"
+    random_world.to_json(response)
+  when "/queries"
+    response.status_code = 200
+    response.headers["Content-Type"] = "application/json"
+
+    JSON.build(response) do |json|
+      json.array do
+        sanitized_query_count(request).times do
+          random_world.to_json(json)
+        end
+      end
+    end
+  when "/fortunes"
+    response.status_code = 200
+    response.headers["Content-Type"] = "text/html; charset=UTF-8"
+
+    data = fortunes
+    additional_fortune = {
+      id:      0,
+      message: "Additional fortune added at request time.",
+    }
+
+    data.push(additional_fortune)
+    data.sort! { |f1, f2| f1[:message] <=> f2[:message] }
+
+    ECR.embed "views/fortunes.ecr", response
+  when "/updates"
+    response.status_code = 200
+    response.headers["Content-Type"] = "application/json"
+
+    JSON.build(response) do |json|
+      json.array do
+        sanitized_query_count(request).times do
+          world = set_world({id: random_world[:id], randomNumber: rand(1..ID_MAXIMUM)})          
+          world.to_json(json)
+        end
+      end
+    end
   else
     response.status_code = 404
   end
 end
 
-server.listen(reuse_port: true)
+private def random_world
+  id = rand(1..ID_MAXIMUM)
+  random_number = APPDB.query_one("SELECT randomNumber FROM world WHERE id = $1", id, as: 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.query_params["queries"].as(String)
+  queries = queries.to_i? || 1
+  queries.clamp(1..500)
+end
+
+server.listen(reuse_port: true)

+ 3 - 1
frameworks/Crystal/crystal/setup.sh

@@ -1,6 +1,8 @@
 #!/bin/bash
 
-fw_depends crystal
+fw_depends postgresql crystal
+
+shards install
 
 crystal build --release server.cr -o server.out
 

+ 10 - 0
frameworks/Crystal/crystal/shard.lock

@@ -0,0 +1,10 @@
+version: 1.0
+shards:
+  db:
+    github: crystal-lang/crystal-db
+    version: 0.4.2
+
+  pg:
+    github: will/crystal-pg
+    version: 0.13.3
+

+ 9 - 0
frameworks/Crystal/crystal/shard.yml

@@ -0,0 +1,9 @@
+name: "crystal"
+version: "0.0.1"
+
+dependencies:
+  pg:
+    github: "will/crystal-pg"
+    version: "0.13.3"
+
+license: "MIT"

+ 20 - 0
frameworks/Crystal/crystal/views/fortunes.ecr

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>Fortunes</title>
+</head>
+<body>
+	<table>
+		<tr>
+		<th>id</th>
+		<th>message</th>
+		</tr>
+		<% data.each do |fortune| %>
+			<tr>
+			<td><%= fortune[:id] %></td>
+			<td><%= HTML.escape(fortune[:message]) %></td>
+			</tr>
+		<% end %>
+	</table>
+</body>
+</html>