danielsz/system

Reloading dynamic Ring Handler

theronic opened this issue · 1 comments

How do I refresh my Ring/Compojure handler when the handler is built by a function since it depends on other components?

I can't get System to reload my changes because it captures everything in a closure when the RingHandler component is made. To see any changes, I need to force a reset.

All the examples out there define a global app or handler var, but this is not how real handlers are built.

Example:

(defn make-handler
  "Returns a ring handler."
  [app]
  (compojure/routes
    (-> (make-ws-handler chsk-handlers)
        (wrap-standard-middleware))
    (make-document-handlers)
    (cond-> (make-public-handler app)
            true (wrap-standard-middleware)
            true (wrap-restful-format :formats [:json :edn :transit-json])
            true (wrap-my-exceptions))))

Ring Handler component:

(defrecord RingHandler [routes]
  component/Lifecycle
  (start [component]
    component
    ; note we were stopping this component explicitly. dunno why
    ; todo: use the routes you are getting from routes.
    ; not using them at the moment. the handler should just handle the routes
    ; and it should understand middleware / sente what it needs.
    (let [handler (make-handler
                    {:knowbase knowbase
                     :chsk-handlers       remote
                     :fallback-handlers (:handlers routes)})]
      (assoc component :handler handler)))
  (stop [component]
    (dissoc component :handler)))

System

(defn dev-system
  ([overrides]
   (component/system-map
     :ring-handler (component/using (handler/new-ring-handler) [])
     :web (component/using (server/new-http-server) [:ring-handler])
     ))
  ([] (dev-system {})))

You are writing your own handler component which is fine but unsupported. System provides an integrated way to define Ring apps via its own components. The handler, endpoint and middleware components in system, sometimes referred to as the Raamwerk mini-framework, act as the basic building blocks and you might want to have a look at them. It requires only little effort to adapt an existing Ring application to the style Raamwerk promotes.

The following examples in the repo use Raamwerk and might prove useful:
https://github.com/danielsz/system-dependency-injection
https://github.com/danielsz/system-websockets
https://github.com/danielsz/system-api-example
https://github.com/danielsz/system-api-example