I am trying to start my clojure application on my heroku dyno but I keep getting and error in my stuartsierra.component/start.
(defrecord Listener [listener]
component/Lifecycle
(start [component]
(assoc component :listener (yada/listener
["/"
[(view/view-route)
routes/route-handler
["public/" (new-directory-resource (io/file "target/cljsbuild/public") {})]
[true (as-resource nil)]]]
(or (env :port) (get (read-config "resources/config.edn" {:profile :dev}) :webserver))
)))
(stop [component]
(when-let [close (-> component :listener :close)]
(close))
(assoc component :listener nil)))
(defn new-system []
(component/system-map
:listener (map->Listener {})
))
(def system nil)
(defn init []
(alter-var-root #'system
(constantly (new-system))))
(defn start []
(alter-var-root #'system component/start))
(defn stop []
(alter-var-root #'system
(fn [s] (when s (component/stop s)))))
(defn go []
(init)
(start))
(defn reset []
(stop)
(refresh :after 'web.core/go))
(defn -main
[& [port]]
(component/start (new-system))
(println "System Started")
@(promise))
This is my core file with all my stuartsierra.component code. This all works perfectly when I run it locally on my laptop doing lein repl and then (go) and also when I just do lein run. So I am confused as to why it doesn't work when I push this to the heroku dyno.
The error I get is
Exception in thread "main" clojure.lang.ExceptionInfo: Error in component :listener in system com.stuartsierra.component.SystemMap calling #'com.stuartsierra.component/start {:reason :com.stuartsierra.component/component-function-threw-exception, :function #'com.stuartsierra.component/start, :system-key :listener, :component #web.core.Listener{:listener nil}, :system #<SystemMap>}, compiling:(/tmp/form-init9049917434081554913.clj:1:73)
This is telling me that my :listener is nil in the system-map. When I check locally (doing lein repl (go)) in (keys system) is (:listener) which is good so that means that the listener is starting and is in the system.
When I do (-> system :listener) I get #web.core.Listener{:listener {:port 3300, :close #object[yada.aleph$listener$fn__21671 0xa5d4865 "yada.aleph$listener$fn__21671@a5d4865"], :server #object[aleph.netty$start_server$reify__13574 0x3cc9a232 "aleph.netty$start_server$reify__13574@3cc9a232"]}} which is perfect as the port has loaded up (3300) and the server has started.
This makes it all the more confusing as to why the :listener is nil in my heroku app
Any help would be much appreciated. Thanks
Heroku dynamically assigns ports to web: processes. The value of that port should be passed to the Clojure code using the Heroku environment variable $PORT
So the Procfile should include the port variable
web: lein with-profile production trampoline run -m web.core $PORT
This port value should be passed into the component from the -main function in the web.core namespace.
As Heroku will build an uberjar (your Clojure application + Clojure itself) if the :uberjar-name "webapp.jar" and :min-lein-version "2.0.0" settings are included in project.clj file.
The java command can then be used to run the Clojure application, using the uberjar that Heroku builds and using fewer resources
web: java -jar target/webapp.jar $PORT
Reference:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With