Browse Source

Merge pull request #1958 from yogthos/master

updated Luminus benchmark to latest Luminus version
Mike Smith 9 years ago
parent
commit
dd906d0d9e
36 changed files with 435 additions and 411 deletions
  1. 1 6
      frameworks/Clojure/luminus/README.md
  2. 2 2
      frameworks/Clojure/luminus/benchmark_config.json
  3. 3 1
      frameworks/Clojure/luminus/hello/.gitignore
  4. 2 0
      frameworks/Clojure/luminus/hello/README.md
  5. 1 1
      frameworks/Clojure/luminus/hello/env/dev/clj/hello/env.clj
  6. 15 0
      frameworks/Clojure/luminus/hello/env/dev/clj/user.clj
  7. 5 0
      frameworks/Clojure/luminus/hello/env/dev/resources/config.edn
  8. 25 0
      frameworks/Clojure/luminus/hello/env/dev/resources/log4j.properties
  9. 1 1
      frameworks/Clojure/luminus/hello/env/prod/clj/hello/env.clj
  10. 3 0
      frameworks/Clojure/luminus/hello/env/prod/resources/config.edn
  11. 7 3
      frameworks/Clojure/luminus/hello/env/prod/resources/log4j.properties
  12. 3 0
      frameworks/Clojure/luminus/hello/env/test/resources/config.edn
  13. 0 2
      frameworks/Clojure/luminus/hello/profiles.clj
  14. 35 36
      frameworks/Clojure/luminus/hello/project.clj
  15. 0 1
      frameworks/Clojure/luminus/hello/resources/migrations/20160114154818-add-users-table.down.sql
  16. 0 9
      frameworks/Clojure/luminus/hello/resources/migrations/20160114154818-add-users-table.up.sql
  17. 28 1
      frameworks/Clojure/luminus/hello/resources/public/css/screen.css
  18. 8 13
      frameworks/Clojure/luminus/hello/resources/sql/queries.sql
  19. 0 3
      frameworks/Clojure/luminus/hello/resources/templates/home.html
  20. 10 0
      frameworks/Clojure/luminus/hello/src/clj/hello/config.clj
  21. 56 0
      frameworks/Clojure/luminus/hello/src/clj/hello/core.clj
  22. 74 0
      frameworks/Clojure/luminus/hello/src/clj/hello/db/core.clj
  23. 21 0
      frameworks/Clojure/luminus/hello/src/clj/hello/handler.clj
  24. 0 0
      frameworks/Clojure/luminus/hello/src/clj/hello/layout.clj
  25. 10 4
      frameworks/Clojure/luminus/hello/src/clj/hello/middleware.clj
  26. 68 0
      frameworks/Clojure/luminus/hello/src/clj/hello/routes/home.clj
  27. 0 41
      frameworks/Clojure/luminus/hello/src/hello/core.clj
  28. 0 117
      frameworks/Clojure/luminus/hello/src/hello/db/core.clj
  29. 0 21
      frameworks/Clojure/luminus/hello/src/hello/db/migrations.clj
  30. 0 41
      frameworks/Clojure/luminus/hello/src/hello/handler.clj
  31. 0 53
      frameworks/Clojure/luminus/hello/src/hello/routes/home.clj
  32. 36 0
      frameworks/Clojure/luminus/hello/test/clj/hello/test/db/core.clj
  33. 0 0
      frameworks/Clojure/luminus/hello/test/clj/hello/test/handler.clj
  34. 0 34
      frameworks/Clojure/luminus/hello/test/hello/test/db/core.clj
  35. 1 1
      frameworks/Clojure/luminus/setup.sh
  36. 20 20
      frameworks/Clojure/luminus/source_code

+ 1 - 6
frameworks/Clojure/luminus/README.md

@@ -11,10 +11,5 @@ This is the [Luminus](http://www.luminusweb.net/) portion of a [benchmarking tes
 * [Database test source](hello/src/hello/handler.clj)
 
 ## Infrastructure Software Versions
-The dependencies are documented in [project.clj](hello/project.clj),
-but the main ones are:
-
-* [Clojure 1.8.0](http://clojure.org/)
-* [Compojure 1.4.0](https://github.com/weavejester/compojure)
-* [Cheshire 5.5.0](https://github.com/dakrone/cheshire), which in turn uses [Jackson](http://jackson.codehaus.org/)
 
+The dependencies are documented in [project.clj](hello/project.clj).

+ 2 - 2
frameworks/Clojure/luminus/benchmark_config.json

@@ -3,12 +3,12 @@
   "tests": [{
     "default": {
       "setup_file": "setup",
-      "json_url": "/json",
+      "json_url": "/io/json",
+      "plaintext_url": "/io/plaintext",
       "db_url": "/db",
       "query_url": "/queries/",
       "fortune_url": "/fortunes",
       "update_url": "/updates/",
-      "plaintext_url": "/plaintext",
       "port": 3000,
       "approach": "Realistic",
       "classification": "Platform",

+ 3 - 1
frameworks/Clojure/luminus/hello/.gitignore

@@ -6,5 +6,7 @@ pom.xml
 *.jar
 *.class
 /.lein-*
+profiles.clj
 /.env
-*.log
+.nrepl-port
+/log

+ 2 - 0
frameworks/Clojure/luminus/hello/README.md

@@ -1,5 +1,7 @@
 # hello
 
+generated using Luminus version "2.9.10.13"
+
 FIXME
 
 ## Prerequisites

+ 1 - 1
frameworks/Clojure/luminus/hello/env/dev/clj/hello/config.clj → frameworks/Clojure/luminus/hello/env/dev/clj/hello/env.clj

@@ -1,4 +1,4 @@
-(ns hello.config
+(ns hello.env
   (:require [selmer.parser :as parser]
             [clojure.tools.logging :as log]
             [hello.dev-middleware :refer [wrap-dev]]))

+ 15 - 0
frameworks/Clojure/luminus/hello/env/dev/clj/user.clj

@@ -0,0 +1,15 @@
+(ns user
+  (:require [mount.core :as mount]
+            hello.core))
+
+(defn start []
+  (mount/start-without #'hello.core/repl-server))
+
+(defn stop []
+  (mount/stop-except #'hello.core/repl-server))
+
+(defn restart []
+  (stop)
+  (start))
+
+

+ 5 - 0
frameworks/Clojure/luminus/hello/env/dev/resources/config.edn

@@ -0,0 +1,5 @@
+{:dev true
+ :port 3000
+ ;; when :nrepl-port is set the application starts the nREPL server on load
+ :nrepl-port 7000
+ :database-url "jdbc:postgresql://127.0.0.1:5432/hello_world?user=benchmarkdbuser&password=benchmarkdbpass&jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"}

+ 25 - 0
frameworks/Clojure/luminus/hello/env/dev/resources/log4j.properties

@@ -0,0 +1,25 @@
+### stdout appender
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=[%d][%p][%c] %m%n
+
+### rolling file appender
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=./log/hello.log
+
+log4j.appender.R.MaxFileSize=100KB
+log4j.appender.R.MaxBackupIndex=20
+
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=[%d][%p][%c] %m%n
+
+### suppress 3rd party debug logs
+log4j.logger.org.xnio.nio=INFO
+log4j.logger.com.zaxxer.hikari=INFO
+
+
+
+### root logger sets the minimum logging level
+### and aggregates the appenders
+log4j.rootLogger=DEBUG, stdout, R

+ 1 - 1
frameworks/Clojure/luminus/hello/env/prod/clj/hello/config.clj → frameworks/Clojure/luminus/hello/env/prod/clj/hello/env.clj

@@ -1,4 +1,4 @@
-(ns hello.config
+(ns hello.env
   (:require [clojure.tools.logging :as log]))
 
 (def defaults

+ 3 - 0
frameworks/Clojure/luminus/hello/env/prod/resources/config.edn

@@ -0,0 +1,3 @@
+{:production true
+ :port 3000
+ :database-url "jdbc:postgresql://127.0.0.1:5432/hello_world?user=benchmarkdbuser&password=benchmarkdbpass&jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"}

+ 7 - 3
frameworks/Clojure/luminus/hello/resources/log4j.properties → frameworks/Clojure/luminus/hello/env/prod/resources/log4j.properties

@@ -4,6 +4,10 @@ log4j.appender.stdout.Target=System.out
 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
 log4j.appender.stdout.layout.ConversionPattern=[%d][%p][%c] %m%n
 
+### rolling file appender
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=./log/hello.log
+
 log4j.appender.R.MaxFileSize=100KB
 log4j.appender.R.MaxBackupIndex=20
 
@@ -11,11 +15,11 @@ log4j.appender.R.layout=org.apache.log4j.PatternLayout
 log4j.appender.R.layout.ConversionPattern=[%d][%p][%c] %m%n
 
 ### suppress 3rd party debug logs
-log4j.logger.org.xnio.nio=FATAL
-log4j.logger.com.zaxxer.hikari=FATAL
+log4j.logger.org.xnio.nio=INFO
+log4j.logger.com.zaxxer.hikari=INFO
 
 
 
 ### root logger sets the minimum logging level
 ### and aggregates the appenders
-log4j.rootLogger=FATAL, stdout
+log4j.rootLogger=INFO, stdout, R

+ 3 - 0
frameworks/Clojure/luminus/hello/env/test/resources/config.edn

@@ -0,0 +1,3 @@
+{:test true
+ :port 3001
+ :nrepl-port 7001} ;; when :nrepl-port is set the application starts the nREPL server on load

+ 0 - 2
frameworks/Clojure/luminus/hello/profiles.clj

@@ -1,2 +0,0 @@
-{:profiles/dev  {:env {:database-url "jdbc:mysql://localhost:3306/hello_dev?user=db_user_name_here&password=db_user_password_here"}}
- :profiles/test {:env {:database-url "jdbc:mysql://localhost:3306/hello_test?user=db_user_name_here&password=db_user_password_here"}}}

+ 35 - 36
frameworks/Clojure/luminus/hello/project.clj

@@ -1,67 +1,66 @@
 (defproject hello "0.1.0-SNAPSHOT"
 
-  :description "Luminus framework benchmarks"
-  :url "https://github.com/TechEmpower/FrameworkBenchmarks/tree/master/frameworks/Clojure/luminus"
+  :description "FIXME: write description"
+  :url "http://example.com/FIXME"
 
   :dependencies [[org.clojure/clojure "1.8.0"]
-                 [selmer "1.0.0"]
-                 [markdown-clj "0.9.85"]
-                 [environ "1.0.1"]
+                 [selmer "1.0.2"]
+                 [markdown-clj "0.9.86"]
                  [ring-middleware-format "0.7.0"]
                  [metosin/ring-http-response "0.6.5"]
                  [bouncer "1.0.0"]
-                 [org.webjars/bootstrap "3.3.6"]
-                 [org.webjars/jquery "2.2.0"]
+                 [org.webjars/bootstrap "4.0.0-alpha.2"]
+                 [org.webjars/font-awesome "4.5.0"]
+                 [org.webjars.bower/tether "1.1.1"]
+                 [org.webjars/jquery "2.2.1"]
                  [org.clojure/tools.logging "0.3.1"]
-                 [org.slf4j/slf4j-log4j12 "1.7.13"]
-                 [org.apache.logging.log4j/log4j-core "2.5"]
                  [com.taoensso/tower "3.0.2"]
-                 [compojure "1.4.0"]
+                 [compojure "1.5.0"]
                  [ring-webjars "0.1.1"]
-                 [ring/ring-defaults "0.1.5"]
-                 [ring "1.4.0" :exclusions [ring/ring-jetty-adapter]]
-                 [mount "0.1.8"]
-                 [luminus-nrepl "0.1.2"]
-                 [migratus "0.8.8"]
-                 [conman "0.2.9"]
-                 [org.postgresql/postgresql "9.4.1208"]
+                 [ring/ring-defaults "0.2.0"]
+                 [mount "0.1.10"]
+                 [cprop "0.1.6"]
+                 [org.clojure/tools.cli "0.3.3"]
+                 [luminus-nrepl "0.1.4"]
                  [org.webjars/webjars-locator-jboss-vfs "0.1.0"]
-                 [luminus-immutant "0.1.0"]]
+                 [luminus-immutant "0.1.9"]
+                 [luminus-migrations "0.1.0"]
+                 [conman "0.4.5"]
+                 [org.postgresql/postgresql "9.4-1206-jdbc4"]
+                 [luminus-log4j "0.1.3"]]
 
   :min-lein-version "2.0.0"
-  :uberjar-name "hello.jar"
-  :jvm-opts ["-server"]
+
+  :jvm-opts ["-server" "-Dconf=.lein-env"]
+  :source-paths ["src/clj"]
   :resource-paths ["resources"]
 
   :main hello.core
-  :migratus {:store :database}
+  :migratus {:store :database :db ~(get (System/getenv) "DATABASE_URL")}
 
-  :plugins [[lein-environ "1.0.1"]
-            [migratus-lein "0.2.0"]]
+  :plugins [[lein-cprop "1.0.1"]
+            [migratus-lein "0.2.6"]]
   :profiles
   {:uberjar {:omit-source true
-             :env {:production true}
+
              :aot :all
-             :source-paths ["env/prod/clj"]}
+             :uberjar-name "hello.jar"
+             :source-paths ["env/prod/clj"]
+             :resource-paths ["env/prod/resources"]}
    :dev           [:project/dev :profiles/dev]
    :test          [:project/test :profiles/test]
-   :project/dev  {:dependencies [[prone "1.0.0"]
+   :project/dev  {:dependencies [[prone "1.0.2"]
                                  [ring/ring-mock "0.3.0"]
                                  [ring/ring-devel "1.4.0"]
                                  [pjstadig/humane-test-output "0.7.1"]
                                  [mvxcvi/puget "1.0.0"]]
 
 
-                  :source-paths ["env/dev/clj"]
-                  :repl-options {:init-ns hello.core}
+                  :source-paths ["env/dev/clj" "test/clj"]
+                  :resource-paths ["env/dev/resources"]
+                  :repl-options {:init-ns user}
                   :injections [(require 'pjstadig.humane-test-output)
-                               (pjstadig.humane-test-output/activate!)]
-                  ;;when :nrepl-port is set the application starts the nREPL server on load
-                  :env {:dev        true
-                        :port       3000
-                        :nrepl-port 7000}}
-   :project/test {:env {:test       true
-                        :port       3001
-                        :nrepl-port 7001}}
+                               (pjstadig.humane-test-output/activate!)]}
+   :project/test {:resource-paths ["env/dev/resources" "env/test/resources"]}
    :profiles/dev {}
    :profiles/test {}})

+ 0 - 1
frameworks/Clojure/luminus/hello/resources/migrations/20160114154818-add-users-table.down.sql

@@ -1 +0,0 @@
-DROP TABLE users;

+ 0 - 9
frameworks/Clojure/luminus/hello/resources/migrations/20160114154818-add-users-table.up.sql

@@ -1,9 +0,0 @@
-CREATE TABLE users
-(id VARCHAR(20) PRIMARY KEY,
- first_name VARCHAR(30),
- last_name VARCHAR(30),
- email VARCHAR(30),
- admin BOOLEAN,
- last_login TIME,
- is_active BOOLEAN,
- pass VARCHAR(300));

+ 28 - 1
frameworks/Clojure/luminus/hello/resources/public/css/screen.css

@@ -2,5 +2,32 @@ html,
 body {
 	font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
     height: 100%;
-    padding-top: 40px;
 }
+.navbar {
+  margin-bottom: 10px;
+}
+.navbar-brand {
+  float: none;
+}
+.navbar-nav .nav-item {
+  float: none;
+}
+.navbar-divider,
+.navbar-nav .nav-item+.nav-item,
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 0;
+}
+@media (min-width: 34em) {
+  .navbar-brand {
+    float: left;
+  }
+  .navbar-nav .nav-item {
+    float: left;
+  }
+  .navbar-divider,
+  .navbar-nav .nav-item+.nav-item,
+  .navbar-nav .nav-link + .nav-link {
+    margin-left: 1rem;
+  }
+}
+

+ 8 - 13
frameworks/Clojure/luminus/hello/resources/sql/queries.sql

@@ -1,18 +1,13 @@
---name: get-world
--- Query a World record from the database
-SELECT * FROM world
-WHERE id = :id
+-- :name get-worlds :? :*
+SELECT * FROM "World"
+WHERE id IN (:v*:ids)
 
---name: get-all-fortunes
+--:name get-all-fortunes :? :*
 -- select all records from the fortune table
-SELECT * FROM fortune
+SELECT * FROM "Fortune"
 
---name: update-world<!
+-- :name update-world! :! :1
 -- update an existing world record
-UPDATE world
-SET randomNumber = :randomNumber
+UPDATE "World"
+SET "randomnumber" = :randomNumber
 WHERE id = :id
-
---name: get-all-fortunes
--- query all fortune records
-SELECT id, message FROM fortune

+ 0 - 3
frameworks/Clojure/luminus/hello/resources/templates/home.html

@@ -1,7 +1,5 @@
 {% extends "base.html" %}
-
 {% block content %}
-
 <table>
   <tr>
     <th>id</th>
@@ -14,5 +12,4 @@
   </tr>
   {% endfor %}
 </table>
-
 {% endblock %}

+ 10 - 0
frameworks/Clojure/luminus/hello/src/clj/hello/config.clj

@@ -0,0 +1,10 @@
+(ns hello.config
+  (:require [cprop.core :refer [load-config]]
+            [cprop.source :as source]
+            [mount.core :refer [args defstate]]))
+
+(defstate env :start (load-config
+                       :merge
+                       [(args)
+                        (source/from-system-props)
+                        (source/from-env)]))

+ 56 - 0
frameworks/Clojure/luminus/hello/src/clj/hello/core.clj

@@ -0,0 +1,56 @@
+(ns hello.core
+  (:require [hello.handler :as handler]
+            [luminus.repl-server :as repl]
+            [luminus.http-server :as http]
+            [hello.config :refer [env]]
+            [clojure.tools.cli :refer [parse-opts]]
+            [clojure.tools.logging :as log]
+            [hello.env :refer [defaults]]
+            [luminus.logger :as logger]
+            [mount.core :as mount])
+  (:gen-class))
+
+(def cli-options
+  [["-p" "--port PORT" "Port number"
+    :parse-fn #(Integer/parseInt %)]])
+
+(mount/defstate http-server
+                :start
+                (http/wrap-handler
+                  (http/start
+                    (-> env
+                        (assoc
+                          :handler handler/default-handler
+                          :io-threads (* 2 (.availableProcessors (Runtime/getRuntime)))
+                          :worker-threads 200)
+                        (update :port #(or (-> env :options :port) %))))
+                  handler/io-handler {:path "/io" :dispatch? false})
+                :stop
+                (http/stop http-server))
+
+(mount/defstate repl-server
+                :start
+                (when-let [nrepl-port (env :nrepl-port)]
+                  (repl/start {:port nrepl-port}))
+                :stop
+                (when repl-server
+                  (repl/stop repl-server)))
+
+(defn stop-app []
+  (doseq [component (:stopped (mount/stop))]
+    (log/info component "stopped"))
+  (shutdown-agents))
+
+(defn start-app [args]
+  (logger/init (:log-config env))
+  (doseq [component (-> args
+                        (parse-opts cli-options)
+                        mount/start-with-args
+                        :started)]
+    (log/info component "started"))
+  ((:init defaults))
+  (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app)))
+
+(defn -main [& args]
+  (start-app args))
+

+ 74 - 0
frameworks/Clojure/luminus/hello/src/clj/hello/db/core.clj

@@ -0,0 +1,74 @@
+(ns hello.db.core
+  (:require
+    [cheshire.core :refer [generate-string parse-string]]
+    [clojure.java.jdbc :as jdbc]
+    [conman.core :as conman]
+    [hello.config :refer [env]]
+    [mount.core :refer [defstate]]
+    clojure.set)
+  (:import org.postgresql.util.PGobject
+           org.postgresql.jdbc4.Jdbc4Array
+           clojure.lang.IPersistentMap
+           clojure.lang.IPersistentVector
+           [java.sql
+            BatchUpdateException
+            Date
+            Timestamp
+            PreparedStatement]))
+
+(defstate ^:dynamic *db*
+          :start (conman/connect!
+                   {:adapter    :postgresql
+                    :init-size  10
+                    :min-idle   1
+                    :max-idle   10
+                    :max-active 64
+                    :jdbc-url   (:database-url env)})
+          :stop (conman/disconnect! *db*))
+
+(conman/bind-connection *db* "sql/queries.sql")
+
+;; queries
+
+(defn get-query-count [queries]
+  "Parse provided string value of query count, clamping values to between 1 and 500."
+  (let [n (try (Integer/parseInt queries)
+               (catch Exception _ 1))] ; default to 1 on parse failure
+    (cond
+      (< n 1)   1
+      (> n 500) 500
+      :else     n)))
+
+(defn rename-keys [results]
+  (map #(clojure.set/rename-keys % {:randomnumber :randomNumber}) results))
+
+(defn run-queries
+  "Run the specified number of queries, return the results"
+  [queries]
+  (->> {:ids (repeatedly (get-query-count queries) #(inc (rand-int 9999)))}
+      get-worlds
+      rename-keys))
+
+(defn get-fortunes []
+   "Fetch the full list of Fortunes from the database, sort them by the fortune
+  message text, and then return the results."
+  (sort-by
+   :message
+   (conj (rename-keys (get-all-fortunes))
+         {:id 0 :message "Additional fortune added at request time."})))
+
+(defn set-random-number!
+  "set a new randomNumber, persist, and return the record"
+  [{:keys [id]}]
+  (let [w {:id id :randomNumber (inc (rand-int 9999))}]
+    (try
+        (update-world! w)
+        (catch java.sql.BatchUpdateException e
+          (throw (.getNextException e))))
+    w))
+
+(defn update-and-persist
+  "Changes the :randomNumber of a number of world entities.
+  Persists the changes to sql then returns the updated entities"
+  [queries]
+  (doall (map set-random-number! (run-queries queries))))

+ 21 - 0
frameworks/Clojure/luminus/hello/src/clj/hello/handler.clj

@@ -0,0 +1,21 @@
+(ns hello.handler
+  (:require [compojure.core :refer [routes wrap-routes]]
+            [hello.layout :refer [error-page]]
+            [hello.routes.home :refer [default-routes io-routes]]
+            [compojure.route :as route]))
+
+(def default-handler
+  (routes
+    #'default-routes
+    (route/not-found
+      (:body
+        (error-page {:status 404
+                     :title "page not found"})))))
+
+(def io-handler
+  (routes
+    #'io-routes
+    (route/not-found
+      (:body
+        (error-page {:status 404
+                     :title "page not found"})))))

+ 0 - 0
frameworks/Clojure/luminus/hello/src/hello/layout.clj → frameworks/Clojure/luminus/hello/src/clj/hello/layout.clj


+ 10 - 4
frameworks/Clojure/luminus/hello/src/hello/middleware.clj → frameworks/Clojure/luminus/hello/src/clj/hello/middleware.clj

@@ -1,14 +1,14 @@
 (ns hello.middleware
   (:require [hello.layout :refer [*app-context* error-page]]
             [clojure.tools.logging :as log]
-            [environ.core :refer [env]]
+            [hello.env :refer [defaults]]
+            [hello.config :refer [env]]
             [ring.middleware.flash :refer [wrap-flash]]
             [immutant.web.middleware :refer [wrap-session]]
             [ring.middleware.webjars :refer [wrap-webjars]]
             [ring.middleware.defaults :refer [site-defaults wrap-defaults]]
             [ring.middleware.anti-forgery :refer [wrap-anti-forgery]]
-            [ring.middleware.format :refer [wrap-restful-format]]
-            [hello.config :refer [defaults]])
+            [ring.middleware.format :refer [wrap-restful-format]])
   (:import [javax.servlet ServletContext]))
 
 (defn wrap-context [handler]
@@ -45,7 +45,13 @@
         :title "Invalid anti-forgery token"})}))
 
 (defn wrap-formats [handler]
-  (wrap-restful-format handler {:formats [:json-kw :transit-json :transit-msgpack]}))
+  (let [wrapped (wrap-restful-format
+                  handler
+                  {:formats [:json-kw :transit-json :transit-msgpack]})]
+    (fn [request]
+      ;; disable wrap-formats for websockets
+      ;; since they're not compatible with this middleware
+      ((if (:websocket? request) handler wrapped) request))))
 
 (defn wrap-base [handler]
   (-> ((:middleware defaults) handler)

+ 68 - 0
frameworks/Clojure/luminus/hello/src/clj/hello/routes/home.clj

@@ -0,0 +1,68 @@
+(ns hello.routes.home
+  (:require [hello.layout :as layout]
+            [hello.db.core :as db]
+            [compojure.core :refer [defroutes GET]]
+            [ring.util.http-response :as response]
+            [clojure.java.io :as io]
+            [ring.util.response :refer [content-type]]
+            [cheshire.core :refer [generate-string]]))
+
+(defn encode-json-response [rsp]
+  (-> rsp
+      generate-string
+      response/ok
+      (content-type "application/json")))
+
+(defn json-serialization
+  "Test 1: JSON serialization"
+  []
+  (-> {:message "Hello, World!"}
+      generate-string
+      response/ok
+      (content-type "application/json")))
+
+(defn single-query-test
+  "Test 2: Single database query"
+  []
+  (-> 1
+      db/run-queries
+      first
+      encode-json-response))
+
+(defn multiple-query-test
+  "Test 3: Multiple database query"
+  [queries]
+  (-> queries
+      db/run-queries
+      encode-json-response))
+
+(defn fortunes
+  "Test 4: Fortunes"
+  []
+  (layout/render "home.html" {:messages (db/get-fortunes)}))
+
+(defn db-update
+  "Test 5: Database updates"
+  [queries]
+  (-> queries
+      db/update-and-persist
+      encode-json-response))
+
+(def plaintext
+  "Test 6: Plaintext"
+  (->
+    (response/ok "Hello, World!")
+    (content-type "text/plain")))
+
+(defroutes io-routes
+  (GET "/plaintext"        [] plaintext)
+  (GET "/json"             [] (json-serialization)))
+
+(defroutes default-routes
+  (GET "/"                 []        "Hello, World!")
+  (GET "/db"               []        (single-query-test))
+  (GET "/queries/"         []        (multiple-query-test 1))
+  (GET "/queries/:queries" [queries] (multiple-query-test queries))
+  (GET "/fortunes"         []        (fortunes))
+  (GET "/updates/"         []        (db-update 1))
+  (GET "/updates/:queries" [queries] (db-update queries)))

+ 0 - 41
frameworks/Clojure/luminus/hello/src/hello/core.clj

@@ -1,41 +0,0 @@
-(ns hello.core
-  (:require [hello.handler :refer [app init destroy]]
-            [luminus.repl-server :as repl]
-            [luminus.http-server :as http]
-            [hello.db.migrations :as migrations]
-            [environ.core :refer [env]])
-  (:gen-class))
-
-(defn parse-port [port]
-  (when port
-    (cond
-      (string? port) (Integer/parseInt port)
-      (number? port) port
-      :else          (throw (Exception. (str "invalid port value: " port))))))
-
-(defn http-port [port]
-  (parse-port (or port (env :port) 3000)))
-
-(defn stop-app []
-  (repl/stop)
-  (http/stop destroy)
-  (shutdown-agents))
-
-(defn start-app
-  "e.g. lein run 3000"
-  [[port]]
-  (let [port (http-port port)]
-    (.addShutdownHook (Runtime/getRuntime) (Thread. stop-app))
-    (when-let [repl-port (env :nrepl-port)]
-      (repl/start {:port (parse-port repl-port)}))
-    (http/start {:handler app
-                 :init    init
-                 :port    port})))
-
-(defn -main [& args]
-  (cond
-    (some #{"migrate" "rollback"} args)
-    (do (migrations/migrate args) (System/exit 0))
-    :else
-    (start-app args)))
-  

+ 0 - 117
frameworks/Clojure/luminus/hello/src/hello/db/core.clj

@@ -1,117 +0,0 @@
-(ns hello.db.core
-  (:require
-    [cheshire.core :refer [generate-string parse-string]]
-    [clojure.java.jdbc :as jdbc]
-    [conman.core :as conman]
-    [environ.core :refer [env]]
-    [mount.core :refer [defstate]])
-  (:import org.postgresql.util.PGobject
-           org.postgresql.jdbc.PgArray
-           clojure.lang.IPersistentMap
-           clojure.lang.IPersistentVector
-           [java.sql
-            BatchUpdateException
-            Date
-            Timestamp
-            PreparedStatement]))
-
-(def pool-spec
-  {:username   "benchmarkdbuser"
-   :password   "benchmarkdbpass"
-   :jdbc-url   "jdbc:postgresql://127.0.0.1:5432/hello_world?jdbcCompliantTruncation=false&elideSetAutoCommits=true&useLocalSessionState=true&cachePrepStmts=true&cacheCallableStmts=true&alwaysSendSetIsolation=false&prepStmtCacheSize=4096&cacheServerConfiguration=true&prepStmtCacheSqlLimit=2048&zeroDateTimeBehavior=convertToNull&traceProtocol=false&useUnbufferedInput=false&useReadAheadInput=false&maintainTimeStats=false&useServerPrepStmts&cacheRSMetadata=true"
-   :init-size  1
-   :min-idle   1
-   :max-idle   4
-   :max-active 32})
-
-(defn connect! []
-  (let [conn (atom nil)]
-    (conman/connect! conn pool-spec)
-    conn))
-
-(defn disconnect! [conn]
-  (conman/disconnect! conn))
-
-(defstate ^:dynamic *db*
-          :start (connect!)
-          :stop (disconnect! *db*))
-
-(conman/bind-connection *db* "sql/queries.sql")
-
-(defn to-date [sql-date]
-  (-> sql-date (.getTime) (java.util.Date.)))
-
-(extend-protocol jdbc/IResultSetReadColumn
-  Date
-  (result-set-read-column [v _ _] (to-date v))
-
-  Timestamp
-  (result-set-read-column [v _ _] (to-date v))
-
-  PgArray
-  (result-set-read-column [v _ _] (vec (.getArray v)))
-
-  PGobject
-  (result-set-read-column [pgobj _metadata _index]
-    (let [type  (.getType pgobj)
-          value (.getValue pgobj)]
-      (case type
-        "json" (parse-string value true)
-        "jsonb" (parse-string value true)
-        "citext" (str value)
-        value))))
-
-(extend-type java.util.Date
-  jdbc/ISQLParameter
-  (set-parameter [v ^PreparedStatement stmt idx]
-    (.setTimestamp stmt idx (Timestamp. (.getTime v)))))
-
-(defn to-pg-json [value]
-  (doto (PGobject.)
-    (.setType "jsonb")
-    (.setValue (generate-string value))))
-
-(extend-protocol jdbc/ISQLValue
-  IPersistentMap
-  (sql-value [value] (to-pg-json value))
-  IPersistentVector
-  (sql-value [value] (to-pg-json value)))
-
-;; queries
-
-(defn get-world-random
-  "Query a random World record between 1 and 10,000 from the database"
-  []
-  (get-world {:id (inc (rand-int 9999))}))
-
-(defn get-query-count [queries]
-  "Parse provided string value of query count, clamping values to between 1 and 500."
-  (let [n (try (Integer/parseInt queries)
-               (catch Exception e 1))] ; default to 1 on parse failure
-    (cond
-      (< n 1) 1
-      (> n 500) 500
-      :else n)))
-
-(defn run-queries
-  "Run the specified number of queries, return the results"
-  [queries]
-  (flatten (repeatedly (get-query-count queries) get-world-random)))
-
-(defn get-fortunes []
-   "Fetch the full list of Fortunes from the database, sort them by the fortune
-  message text, and then return the results."
-  (sort-by
-   :message
-   (conj (get-all-fortunes {})
-         {:id 0 :message "Additional fortune added at request time."})))
-
-(defn update-and-persist
-  "Changes the :randomNumber of a number of world entities.
-  Persists the changes to sql then returns the updated entities"
-  [queries]
-  (for [world (-> queries run-queries)]
-    (let [updated-world (assoc world :randomNumber (inc (rand-int 9999)))]
-      (update-world<! updated-world)
-      updated-world)))
-

+ 0 - 21
frameworks/Clojure/luminus/hello/src/hello/db/migrations.clj

@@ -1,21 +0,0 @@
-(ns hello.db.migrations
-  (:require
-    [migratus.core :as migratus]
-    [environ.core :refer [env]]
-    [to-jdbc-uri.core :refer [to-jdbc-uri]]))
-
-(defn parse-ids [args]
-  (map #(Long/parseLong %) (rest args)))
-
-(defn migrate [args]
-  (let [config {:store :database
-                :db {:connection-uri (to-jdbc-uri (:database-url env))}}]
-    (case (first args)
-      "migrate"
-      (if (> (count args) 1)
-        (apply migratus/up config (parse-ids args))
-        (migratus/migrate config))
-      "rollback"
-      (if (> (count args) 1)
-        (apply migratus/down config (parse-ids args))
-        (migratus/rollback config)))))

+ 0 - 41
frameworks/Clojure/luminus/hello/src/hello/handler.clj

@@ -1,41 +0,0 @@
-(ns hello.handler
-  (:require [compojure.core :refer [defroutes routes wrap-routes]]
-            [hello.layout :refer [error-page]]
-            [hello.routes.home :refer [home-routes]]
-            [hello.middleware :as middleware]
-            [clojure.tools.logging :as log]
-            [compojure.route :as route]
-            [environ.core :refer [env]]
-            [hello.config :refer [defaults]]
-            [mount.core :as mount]))
-
-(defn init
-  "init will be called once when
-   app is deployed as a servlet on
-   an app server such as Tomcat
-   put any initialization code here"
-  []
-  (when-let [config (:log-config env)]
-    (org.apache.log4j.PropertyConfigurator/configure config))
-  (doseq [component (:started (mount/start))]
-    (log/info component "started"))
-  ((:init defaults)))
-
-(defn destroy
-  "destroy will be called when your application
-   shuts down, put any clean up code here"
-  []
-  (log/info "hello is shutting down...")
-  (doseq [component (:stopped (mount/stop))]
-    (log/info component "stopped"))
-  (log/info "shutdown complete!"))
-
-(def app-routes
-  (routes
-    (wrap-routes #'home-routes middleware/wrap-csrf)
-    (route/not-found
-      (:body
-        (error-page {:status 404
-                     :title "page not found"})))))
-
-(def app (middleware/wrap-base #'app-routes))

+ 0 - 53
frameworks/Clojure/luminus/hello/src/hello/routes/home.clj

@@ -1,53 +0,0 @@
-(ns hello.routes.home
-  (:require [hello.layout :as layout]
-            [hello.db.core :as db]
-            [compojure.core :refer [defroutes GET]]
-            [ring.util.response :refer [response content-type]]
-            [clojure.java.io :as io]))
-
-(defn json-serialization
-  "Test 1: JSON serialization"
-  []
-  (response {:message "Hello, World!"}))
-
-(defn single-query-test
-  "Test 2: Single database query"
-  []
-  (-> 1 db/run-queries first response))
-
-(defn multiple-query-test
-  "Test 3: Multiple database query"
-  [queries]
-  (-> queries
-      db/run-queries
-      response))
-
-(defn fortunes
-  "Test 4: Fortunes"
-  []
-  (layout/render "home.html" {:messages (db/get-fortunes)}))
-
-(defn db-update
-  "Test 5: Database updates"
-  [queries]
-  (-> queries
-      db/update-and-persist
-      response))
-
-(def plaintext
-  "Test 6: Plaintext"
-  (->
-    (response "Hello, World!")
-    (content-type "text/plain")))
-
-
-(defroutes home-routes
-  (GET "/"                 [] "Hello, World!")
-  (GET "/plaintext"        [] plaintext)
-  (GET "/json"             [] (json-serialization))
-  (GET "/db"               [] (single-query-test))
-  (GET "/queries/"         [] (multiple-query-test 1))
-  (GET "/queries/:queries" [queries] (multiple-query-test queries))
-  (GET "/fortunes"         [] (fortunes))
-  (GET "/updates/"         [] (db-update 1))
-  (GET "/updates/:queries" [queries] (db-update queries)))

+ 36 - 0
frameworks/Clojure/luminus/hello/test/clj/hello/test/db/core.clj

@@ -0,0 +1,36 @@
+(ns hello.test.db.core
+  (:require [hello.db.core :refer [*db*] :as db]
+            [luminus-migrations.core :as migrations]
+            [clojure.test :refer :all]
+            [clojure.java.jdbc :as jdbc]
+            [hello.config :refer [env]]
+            [mount.core :as mount]))
+
+(use-fixtures
+  :once
+  (fn [f]
+    (mount/start
+      #'hello.config/env
+      #'hello.db.core/*db*)
+    (migrations/migrate ["migrate"] (env :database-url))
+    (f)))
+
+(deftest test-users
+  (jdbc/with-db-transaction [t-conn *db*]
+    (jdbc/db-set-rollback-only! t-conn)
+    (is (= 1 (db/create-user!
+               t-conn
+               {:id         "1"
+                :first_name "Sam"
+                :last_name  "Smith"
+                :email      "[email protected]"
+                :pass       "pass"})))
+    (is (= {:id         "1"
+            :first_name "Sam"
+            :last_name  "Smith"
+            :email      "[email protected]"
+            :pass       "pass"
+            :admin      nil
+            :last_login nil
+            :is_active  nil}
+           (db/get-user t-conn {:id "1"})))))

+ 0 - 0
frameworks/Clojure/luminus/hello/test/hello/test/handler.clj → frameworks/Clojure/luminus/hello/test/clj/hello/test/handler.clj


+ 0 - 34
frameworks/Clojure/luminus/hello/test/hello/test/db/core.clj

@@ -1,34 +0,0 @@
-(ns hello.test.db.core
-  (:require [hello.db.core :as db]
-            [hello.db.migrations :as migrations]
-            [clojure.test :refer :all]
-            [clojure.java.jdbc :as jdbc]
-            [conman.core :refer [with-transaction]]
-            [environ.core :refer [env]]
-            [mount.core :as mount]))
-
-(use-fixtures
-  :once
-  (fn [f]
-    (mount/start #'hello.db.core/*db*)
-    (migrations/migrate ["migrate"])
-    (f)))
-
-(deftest test-users
-  (with-transaction [t-conn db/*db*]
-    (jdbc/db-set-rollback-only! t-conn)
-    (is (= 1 (db/create-user!
-               {:id         "1"
-                :first_name "Sam"
-                :last_name  "Smith"
-                :email      "[email protected]"
-                :pass       "pass"})))
-    (is (= [{:id         "1"
-             :first_name "Sam"
-             :last_name  "Smith"
-             :email      "[email protected]"
-             :pass       "pass"
-             :admin      nil
-             :last_login nil
-             :is_active  nil}]
-           (db/get-user {:id "1"})))))

+ 1 - 1
frameworks/Clojure/luminus/setup.sh

@@ -3,7 +3,7 @@
 fw_depends java resin leiningen
 
 # Update db host in the source file
-sed -i 's|:jdbc-url   "jdbc:postgresql://.*/hello_world|:jdbc-url   "jdbc:postgresql://'"${DBHOST}"':5432/hello_world|g' hello/src/hello/db/core.clj
+sed -i 's|127.0.0.1|'"${DBHOST}"'|g' hello/env/prod/resources/config.edn
 
 cd hello
 lein clean

+ 20 - 20
frameworks/Clojure/luminus/source_code

@@ -1,16 +1,18 @@
 ./hello/Procfile
 ./hello/README.md
-./hello/env/dev/clj/hello
-./hello/env/dev/clj/hello/config.clj
 ./hello/env/dev/clj/hello/dev_middleware.clj
-./hello/env/prod/clj/hello
-./hello/env/prod/clj/hello/config.clj
-./hello/profiles.clj
+./hello/env/dev/clj/hello/env.clj
+./hello/env/dev/clj/user.clj
+./hello/env/dev/resources/config.edn
+./hello/env/dev/resources/log4j.properties
+./hello/env/prod/clj/hello/env.clj
+./hello/env/prod/resources/config.edn
+./hello/env/prod/resources/log4j.properties
+./hello/env/test/resources/config.edn
 ./hello/project.clj
 ./hello/resources/docs/docs.md
-./hello/resources/log4j.properties
-./hello/resources/migrations/20160114154818-add-users-table.down.sql
-./hello/resources/migrations/20160114154818-add-users-table.up.sql
+./hello/resources/migrations/20160307145316-add-users-table.down.sql
+./hello/resources/migrations/20160307145316-add-users-table.up.sql
 ./hello/resources/public/css/screen.css
 ./hello/resources/public/favicon.ico
 ./hello/resources/sql/queries.sql
@@ -18,15 +20,13 @@
 ./hello/resources/templates/base.html
 ./hello/resources/templates/error.html
 ./hello/resources/templates/home.html
-./hello/src/hello/core.clj
-./hello/src/hello/db
-./hello/src/hello/db/core.clj
-./hello/src/hello/db/migrations.clj
-./hello/src/hello/handler.clj
-./hello/src/hello/layout.clj
-./hello/src/hello/middleware.clj
-./hello/src/hello/routes
-./hello/src/hello/routes/home.clj
-./hello/test/hello/test/db/core.clj
-./hello/test/hello/test/handler.clj
-
+./hello/src/clj/hello/config.clj
+./hello/src/clj/hello/core.clj
+./hello/src/clj/hello/db/core.clj
+./hello/src/clj/hello/handler.clj
+./hello/src/clj/hello/layout.clj
+./hello/src/clj/hello/middleware.clj
+./hello/src/clj/hello/routes/home.clj
+./hello/test/clj
+./hello/test/clj/hello/test/db/core.clj
+./hello/test/clj/hello/test/handler.clj