Fork me on GitHub
#duct
<
2018-01-04
>
myguidingstar03:01:55

Thanks. The problem I had was that I should have refered to`#ig/ref :duct.logger/timbre` instead of #ig/ref :duct.module/logging in my app handler

quan05:01:43

ah, ref to :duct/logger, then the log module will use timbre

quan05:01:54

:logger #ig/ref :duct/logger

myguidingstar06:01:17

how do I tell ataraxy to use :duct.module.web/api for some route and :duct.module.web/site for the rest?

quan09:01:30

I think it's not supported yet, you may have to add list of middlewares by yourself to ataraxy route config

lambder10:01:22

Hi Folks, any idea how can I automatically have (reset) run on file changes? e.g. how to configure file watch so it resets the duct for me?

weavejester16:01:50

(hawk/watch! [{:paths ["src" "test"] :handler (fn [_ _] (reset))}])

weavejester16:01:24

However, I’d recommend tying the (reset) into your editor. If you’re using Emacs, Vim, Atom or Cursive there are inbuilt ways to bind a key to run a Clojure command.

myguidingstar16:01:15

@weavejester figwheel doesn't reload when cljs files change unless (reset). Is that expected?

weavejester16:01:58

@myguidingstar Yes, that’s right. It’s a deliberate design decision, since it allows you to save and reload in two separate steps.

weavejester16:01:19

So in Emacs, I have a key combination that saves, and a key combination that saves and reloads.

weavejester16:01:51

Having it automatically reload without any way of stopping it was problematic to me.

weavejester16:01:25

There are some changes that persist across multiple files - like changing the way the server and client communicate.

weavejester16:01:01

However, because people ask about it so much, maybe I’ll add a hawk command by default, so you can run something like (watch) and it’ll automatically reload.

weavejester16:01:23

(defn watch []
  (hawk/watch! [{:paths ["src" "test"] :handler (fn [_ _] (reset))}]))

weavejester16:01:45

Putting that in your dev.clj file should mean you can type (watch) and then have it reload automatically.

myguidingstar16:01:05

how do I use different middlware sets for different request handlers in ataraxy?

weavejester16:01:46

You can apply the middleware to the handlers manually, or via Ataraxy’s metadata syntax.

weavejester16:01:08

So with Ataraxy, you can do something like:

{:duct.core/project-ns :foo
 :duct.module/ataraxy {"/foo" ^:bar [:baz]}
 :foo.middleware/bar {}
 :foo.handler/baz {}}

weavejester16:01:55

Metadata keys in the routes are treated as hints for middleware. So the metadata hint ^:bar gets given the middleware from the key :foo.middleware/bar

weavejester16:01:20

Alternatively, you can add middleware manually:

myguidingstar16:01:43

yeah, the traditional ring way

weavejester16:01:07

(defmethod ig/init-key :foo.handler/baz [_ opts]
  (wrap-baz (fn [req] ...)))

weavejester16:01:25

Since the key returns a handler, you can wrap it in whatever middleware you want.

weavejester16:01:47

Finally, you can also add global middleware to :duct.core/handler under the :middleware key.

myguidingstar16:01:42

hmm, say I want :duct.module.web/site for everything except /api which should be only wrapped by :duct.module.web/api

myguidingstar16:01:59

what's the best way to config that?

weavejester16:01:23

@myguidingstar The difference is in what middleware is supplied. The most straightforward way is to use :duct.module.web/site and then add the :duct.middleware.web/format middleware to the :duct.core/handler key.

weavejester16:01:06

So like:

:duct.module.web/site {}
:duct.core/handler {:middleware [#ig/ref :duct.middleware.web/format]}
:duct.middleware.web/format {}

weavejester16:01:44

I intend to write a :duct.middle.web/site+api module that does that for you, but I haven’t gotten around to it.

myguidingstar17:01:01

@weavejester the (watch) above throws this when files change java.lang.IllegalStateException: Can't change/establish root binding of: *ns* with set

weavejester17:01:08

What’s the stack trace? I guess Hawk does something weird?

myguidingstar17:01:21

java.lang.IllegalStateException: Can't change/establish root binding of: *ns* with set
	at clojure.lang.Var.set(Var.java:223)
	at clojure.lang.RT$1.invoke(RT.java:242)
	at clojure.tools.namespace.repl$do_refresh.invokeStatic(repl.clj:95)
	at clojure.tools.namespace.repl$do_refresh.invoke(repl.clj:83)
	at clojure.tools.namespace.repl$refresh.invokeStatic(repl.clj:145)
	at clojure.tools.namespace.repl$refresh.doInvoke(repl.clj:128)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at integrant.repl$reset.invokeStatic(repl.clj:52)
	at integrant.repl$reset.invoke(repl.clj:50)
	at dev$watch$fn__49177.invoke(dev.clj:40)
	at hawk.core$process_handler$fn__32995.invoke(core.clj:41)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.AFn.applyTo(AFn.java:144)
	at clojure.core$apply.invokeStatic(core.clj:657)
	at clojure.core$apply.invoke(core.clj:652)
	at hawk.core$catch_errors$fn__32968.doInvoke(core.clj:8)
	at clojure.lang.RestFn.invoke(RestFn.java:421)
	at clojure.core$binding_conveyor_fn$fn__5476.invoke(core.clj:2028)
	at clojure.lang.AFn.applyToHelper(AFn.java:156)
	at clojure.lang.RestFn.applyTo(RestFn.java:132)
	at clojure.lang.Agent$Action.doRun(Agent.java:114)
	at clojure.lang.Agent$Action.run(Agent.java:163)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

myguidingstar17:01:59

btw, I'm looking at duct.module.web source code. What are those :fn and :req in:

(defmethod ig/init-key ::site [_ options]
  {:req #{:duct/logger}
:fn #(apply-web-module % options (site-config (get-project-ns % options)))})

weavejester17:01:36

The :fn is the function - it transforms the configuration. The :req is the required keys - that’s used for ordering.

myguidingstar17:01:58

so it mutates current config?

weavejester17:01:43

It looks like there’s some weird interaction between Hawk and tools.namespace. I’m not sure how to solve it right now, but I’ll take a look when I get back off holiday. You could try using another file watcher (check http://clojure-toolbox.com).

weavejester17:01:14

It transforms the configuration. So in Duct there are three stages - read, prep, init

weavejester17:01:21

The config is read from the edn

weavejester17:01:33

Then prepped, where the modules transform the configuration

weavejester17:01:38

Then finally initiated.

weavejester17:01:14

The way modules work might change a little in future, though. The same idea will hold, but I think there’s a better way of doing them.

myguidingstar17:01:51

how do I start two http server with different ports?

weavejester17:01:50

Use composite keys:

[:duct.server.http/jetty :foo.server/web] {:port 3001}
[:duct.server.http/jetty :foo.server/api] {:port 3002}

weavejester17:01:27

But be aware that I don’t think the web modules will work with that, since they won’t know which server to use. You’ll need to add the keys in manually.

weavejester17:01:41

All modules do is just transform the configuration, adding new keys.

weavejester17:01:05

Without them, you need to add the keys in manually (or write your own module).

weavejester17:01:55

The web modules essentially just populate :duct.core/handler, add a bunch of middleware, and that’s about it.

weavejester17:01:20

They can wire things up because they look for a single HTTP server. If there are multiple ones, it’s ambiguous.

weavejester17:01:52

You can print config at the REPL to see the configuration after it’s been prepped.

weavejester18:01:55

You’re welcome

weavejester18:01:15

I’m planning on making some changes to how modules work that should make them easier to reason about.