Skip to content
Permalink
Browse files

Re-use JavaScript engines by putting them in a pool.

  • Loading branch information...
pupeno committed Sep 9, 2015
1 parent 57ab9f6 commit 11a652f78ab3949a725d17f74c7877fdda8dbcf7
Showing with 38 additions and 24 deletions.
  1. +2 −1 project.clj
  2. +36 −23 src/clj/projectx/handler.clj
@@ -18,7 +18,8 @@
[environ "1.0.0"]
[org.clojure/clojurescript "1.7.122" :scope "provided"]
[bidi "1.20.3"]
[kibu/pushy "0.3.2"]]
[kibu/pushy "0.3.2"]
[aleph "0.4.0"]]

:plugins [[lein-environ "1.0.0"]
[lein-asset-minifier "0.2.2"]]
@@ -7,32 +7,45 @@
[hiccup.page :refer [include-js include-css]]
[prone.middleware :refer [wrap-exceptions]]
[ring.middleware.reload :refer [wrap-reload]]
[environ.core :refer [env]])
[environ.core :refer [env]]
[aleph.flow :as flow])
(:import [javax.script ScriptEngineManager
Invocable]))
Invocable]
[io.aleph.dirigiste Pools]))

(defn- create-js-engine []
(doto (.getEngineByName (ScriptEngineManager.) "nashorn")
(.eval "var global = this") ; React requires either "window" or "global" to be defined.
(.eval (-> "public/js/server-side.js" ; TODO: load the console polyfill, so that calling console.log is safe.
io/resource
io/reader))))

(def ^:private js-engine-key "js-engine") ; We have one and only one key in the pool, it's a constant.
(def ^:private js-engine-pool
(flow/instrumented-pool
{:generate (fn [_] (create-js-engine))
:controller (Pools/utilizationController 0.9 10000 10000)}))

(defn- render-page [path]
(let [js-engine @(flow/acquire js-engine-pool js-engine-key)]
(try (.invokeMethod
^Invocable js-engine
(.eval js-engine "projectx.core")
"render_page"
(object-array [path]))
(finally (flow/release js-engine-pool js-engine-key js-engine)))))

(defn render-app [path]
(let [js-engine (doto (.getEngineByName (ScriptEngineManager.) "nashorn")
(.eval "var global = this") ; React requires either "window" or "global" to be defined.
(.eval (-> "public/js/server-side.js" ; TODO: load the console polyfill, so that calling console.log is safe.
io/resource
io/reader)))
render-page (fn [path]
(.invokeMethod
^Invocable js-engine
(.eval js-engine "projectx.core")
"render_page"
(object-array [path])))]
(html
[:html
[:head
[:meta {:charset "utf-8"}]
[:meta {:name "viewport"
:content "width=device-width, initial-scale=1"}]
(include-css (if (env :dev) "css/site.css" "css/site.min.css"))]
[:body
[:div#app [:div (render-page path)]]
(include-js "js/app.js")]])))
(html
[:html
[:head
[:meta {:charset "utf-8"}]
[:meta {:name "viewport"
:content "width=device-width, initial-scale=1"}]
(include-css (if (env :dev) "css/site.css" "css/site.min.css"))]
[:body
[:div#app [:div (render-page path)]]
(include-js "js/app.js")]]))

(defn- path [request]
(str (:uri request) ; Build the path the same way ring.util.request/request-url does it: https://github.com/ring-clojure/ring/blob/1.4.0/ring-core/src/ring/util/request.clj#L5

0 comments on commit 11a652f

Please sign in to comment.
You can’t perform that action at this time.