Permalink
Browse files

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

  • Loading branch information...
1 parent 57ab9f6 commit 11a652f78ab3949a725d17f74c7877fdda8dbcf7 @pupeno pupeno committed with pupeno Sep 9, 2015
Showing with 38 additions and 24 deletions.
  1. +2 −1 project.clj
  2. +36 −23 src/clj/projectx/handler.clj
View
@@ -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.