Fork me on GitHub
#duct
<
2018-01-08
>
lambder09:01:47

@weavejester when I do this (hawk/watch! [{:paths ["src" "test"] :handler (fn [_ _] (reset))}]) in REPL I got : java.lang.IllegalStateException: Can't change/establish root binding of: *ns* with set clojure.tools.namespace.repl

weavejester14:01:43

@lambder Yes, @myguidingstar reported that as well. It looks like Hawk and tools.namespace don’t like each other for some reason. Perhaps using bound-fn instead of fn would work? Or perhaps try a different file watch library?

lambder14:01:16

@weavejester this worked for me: (hawk/watch! [{:paths ["src" "test"] :handler (fn [_ _] (binding [*ns* (find-ns 'duct.core)] (reset)))}])

lambder14:01:35

I’m getting some other errors after few resets

weavejester14:01:44

Does bound-fn do anything?

lambder14:01:57

these are associated with postgres db couldn’t take more client connections

lambder14:01:17

what is bound-fn ?

lambder14:01:37

do you mean clojure.core/bound-fn?

weavejester14:01:11

Yes, so:

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

lambder14:01:23

let me try

lambder14:01:37

btw @weavejester any idea what could cause the connection pool to grow by doing (reset) ?

lambder14:01:56

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

lambder14:01:13

but after few resets postgres is failing

weavejester14:01:33

It sounds like it’s not closing the pool correctly. You’re using the Hikaricp key, right? Or just the SQL module?

weavejester14:01:56

Ah, yes, I can see by the stacktrace you are using Hikaricp

weavejester14:01:32

Does this behaviour occur if you use (reset) normally?

lambder14:01:17

let me try

weavejester14:01:52

Ah, sorry, I need to dash. I’ll be back later.

lambder14:01:35

ok, thanks a lot

lambder14:01:45

@weavejester manual reset has no problems

lambder14:01:17

manual reset says :

lambder14:01:24

:reloading ()

lambder14:01:55

whereas the watch style one does : :reloading (firds-mirror4.templates.header firds-mirror4.templates.layout firds-mirror4.templates.login firds-mirror4.templates.index firds-mirror4.handler.core firds-mirror4.handler.example-test)

lambder14:01:02

@weavejester even if I do from repl:

(dotimes [n 50] (do (require '[integrant.repl :refer [clear halt go init prep reset reset-all]])  (reset-all)))
it works fine

lambder15:01:54

@weavejester I tried with the clojure-watch.core lib as well

lambder15:01:15

I’m running into the same postgres connection pool problems

lambder15:01:48

even manual (halt) from repl will not help

lambder15:01:06

I need to close the REPL and start new one

weavejester15:01:37

Okay, I’m briefly back!

weavejester15:01:32

Thanks for investigating this, @lambder. I think I need to look into this in more detail. Clearly something in tools.namespace doesn’t like being executed under some circumstances (perhaps in a separate thread?)

weavejester15:01:59

I take it you’re not using an editor that has REPL integration, like Emacs, Vim, Atom or Cursive, @lambder?

lambder15:01:55

my intuition is that integrant.repl/suspend sees no state/system

lambder15:01:19

I use Cursive

weavejester15:01:32

You might be right, though I don’t know why that would be the case…

weavejester15:01:53

If you’re using Cursive, have you considered binding a keyboard shortcut or button to (reset)?

weavejester15:01:09

Pretty sure you can bind one to save and reset, too.

lambder15:01:26

system is a var in integrant.repl.state

lambder15:01:40

I guess it is mutated via altervarroot

lambder15:01:16

can it be that bound-fn somehow is seeng the old bindings?

weavejester15:01:31

Yes, but it should be untouched by tools.namespace.

lambder15:01:46

sure I can do it by key binding, but I wanted it to be on file change

lambder15:01:57

and now I want to understand why I can’t 😉

lambder15:01:14

I don’t like to give up easily 😉

weavejester15:01:18

I’m curious, too 🙂

weavejester15:01:57

I need to head out now, but if you find anything, let me know. I’m more than happy to add a (watch) function to the dev.clj file in the Duct template.

yogidevbear20:01:52

Hi @weavejester. Any chance you could help me with something. I'm playing around with your duct guide doc (https://github.com/duct-framework/docs/blob/master/GUIDE.rst) adapting my project slightly as a work through it. I'm on the section to do with creating the users handler under Code > Adding Users. My table for the email and password is named authors instead of users and has two extra columns, firstName and lastName. This is my adjusted code for the handler /src/duct_blog/handler/author.clj:

(ns duct-blog.handler.authors
  (:require [ataraxy.response :as response]
            [buddy.hashers :as hashers]
            [clojure.java.jdbc :as jdbc]
            duct.database.sql
            [integrant.core :as ig]))

(defprotocol Authors
  (create-author [db email password firstName lastName]))

(extend-protocol Authors
  duct.database.sql.Boundary
  (create-author [{db :spec} email password firstName lastName]
    (let [pw-hash (hashers/derive password)
          results (jdbc/insert! db :authors {:email email, :password pw-hash, :firstName firstName, :lastName lastName})]
      (-> results ffirst val))))

(defmethod ig/init-key ::create [_ {:keys [db]}]
  (fn [{[_ email password firstName lastName] :ataraxy/result}]
    (let [authorid (create-author db email password firstName lastName)]
      [::response/created (str "/authors/" authorid)])))
I am getting the following error when trying to run (go): IllegalArgumentException No method in multimethod 'init-key' for dispatch value: :integrant.composite/duct-blog.handler.authors.create_5324 clojure.lang.MultiFn.getFn (MultiFn.java:156) Any ideas what I'm doing wrong here? I'm sure you're fairly busy with other things at the moment, but I would be immensely greatful if you could help point me in the right direction. Thanks in advance.

weavejester21:01:09

When you see :integrant-composite/blah, it’s a composite key, so a vector in the configuration.

weavejester21:01:43

Behind the scenes, Integrant converts [:foo :bar] into something like :integrant.composite/foo+bar.

weavejester21:01:20

And that composite key derives from both :foo and :bar. This allows vectors to be treated as normal keywords in the global hierarchy.

weavejester21:01:54

So the error message is saying: you have a composite key in your configuration, and none of the values in the vector have multimethods associated with them.

weavejester21:01:41

Actually, that’s a good point… I could really write a better error message for that!

weavejester21:01:12

Anyway, take a look at your configuration. I suspect that you’ll have misspelled a keyword or something.

yogidevbear21:01:26

So would that mean the issue is stemming from this line? [:post "/authors" {{:keys [email password firstName lastName]} :body-params}]

weavejester21:01:52

No, the associated key

weavejester21:01:10

It might be something like… [:duct-blog.handler.authors.create]?

weavejester21:01:36

What’s the key associated with the ::create multimethod?

yogidevbear21:01:53

[:duct-blog.handler.authors/create]
 {:db #ig/ref :duct.database/sql}

yogidevbear21:01:57

That ☝️ ?

weavejester21:01:22

Ah, yes. I think this might be a bug in Integrant that was recently fixed. I don’t think Integrant was loading namespaces based on their parents.

weavejester21:01:38

So the easiest way to fix it is to remove the vector around the key

weavejester21:01:50

:duct-blog.handler.authors/create
 {:db #ig/ref :duct.database/sql}

weavejester21:01:32

Integrant will look for namespaces matching the key, but I believe that there was a problem in the previous Integrant version that made that not work for composite keys.

yogidevbear21:01:27

Cool, that got me a little further

weavejester21:01:32

So because you’ve made the key into a composite key by wrapping it in a vector, Integrant wasn’t loading the duct-blog.handler.authors namespace.

yogidevbear21:01:46

Got a different error now, but I'll try figure that one out before asking for more help 🙂

weavejester21:01:47

The latest Integrant should work in either case.

yogidevbear21:01:05

Cool. Thanks for the explanation 👍 Makes sense now

weavejester21:01:17

Let me know if you get stuck on your next problem, @yogidevbear.

yogidevbear21:01:14

I'm getting the exact same error message and it happens when trying to run (go)

weavejester21:01:57

Try dropping your dev database and recreating, then. Or fix it manually.

yogidevbear21:01:29

Okay, will give that a try

weavejester21:01:23

Unfortunately I don’t think there’s a lot we can do about errors like that, except perhaps by using some sort of migration DSL, maybe? If the dev can execute arbitrary SQL statements, then there’s always a chance of the database getting into a bad state.

yogidevbear21:01:29

Do I simply delete the dev.sqlite file?

yogidevbear21:01:58

Guessing not 🙂 Deleted the file and re-ran (dev) and (go) and ended up at the same state

weavejester21:01:32

Hm, that should have worked. What’s the error?

yogidevbear21:01:04

user=> (dev)
:loaded
dev=> (go)
:duct.migrator.ragtime/applying :duct-blog.migration/create-authors#d0106059
:duct.migrator.ragtime/applying :duct-blog.migration/create-categories#8a201519
:duct.migrator.ragtime/applying :duct-blog.migration/create-posts#0a8584f9
:duct.migrator.ragtime/applying :duct-blog.migration/create-category-post-groups#97ceabe1

IllegalArgumentException No method in multimethod 'init-key' for dispatch value: :duct-blog.handler.authors/create  clojure.lang.MultiFn.getFn (MultiFn.java:156)

yogidevbear21:01:15

Different error

weavejester21:01:46

Ah, yep, so the db migrates okay, but we’re back to not finding the dispatch value…

weavejester21:01:08

Hm, where is the duct-blog.handler.authors namespace in your project?

yogidevbear21:01:13

src/duct_blog/handler/author.clj

yogidevbear21:01:24

Should that be authors.clj?

yogidevbear21:01:47

There we go 😆

yogidevbear21:01:58

The joys of keyboard and chair

yogidevbear21:01:05

Thank you 👍

weavejester21:01:48

No problem. I wonder if that sort of error could be caught by a linter.

yogidevbear21:01:59

Might be a good idea, although more tools... more complexity maybe?

weavejester21:01:06

I think Eastwood (https://github.com/jonase/eastwood) lints namespace errors.

weavejester21:01:31

Though I don’t think it’ll help you if the ns definition is correct but the keyword in the config file is wrong.