Closed conan closed 3 years ago
When mount auto-reloads a namespace which has been recompiled, the recompiled version is not instrumented, meaning it does not perform spec validation
Can you give an example of what does not go through the validation after reload?
When a mount state is reloaded, it calls its :stop
function followed by its :start
function. It could be that instrumentation is weaved in once, and when mount calls :start
it gets the real function definition rather than the one that was "replaced" by spec's instrumentation.
It's the reloading that causes the problem rather than anything to do with the mount lifecycle. If you reload a namespace, it loses its instrumentation. Namespaces that contain a defstate
get reloaded, which is fantastic, but it breaks the instrumentation.
In another loaded namespace I've called (clojure.spec.test.alpha/instrument)
. I have the following namespace:
(ns stuff
(:require [clojure.spec.alpha :as s]))
(defn my-inc [x]
(+ x 1))
(s/fdef my-inc
:args (s/cat :x int?))
(my-inc :1)
I see this error:
ExceptionInfo Call to #'user/my-inc did not conform to spec:
In: [0] val: :1 fails at: [:args :x] predicate: int?
clojure.core/ex-info (core.clj:4739)
If I modify the namespace (adding a comment or something semantically meaningless) and it gets reloaded, I see this error:
ClassCastException clojure.lang.Keyword cannot be cast to java.lang.Number clojure.lang.Numbers.add (Numbers.java:128)
In this example it's clear what happened in both cases, but in many instances the spec error is much more informative.
I believe you, but I don't use spec/instrument
, so I just want to look at the example with a mount state that has / causes problem reloading to understand the problem better.
I've developed a way of working around this in my user
namespace so I'm closing this. thanks!
In development, I like always to have
clojure.spec.test.alpha/instrument
in effect, which provides spec validation for function calls in the REPL by instrumenting all loaded namespaces.When mount auto-reloads a namespace which has been recompiled, the recompiled version is not instrumented, meaning it does not perform spec validation. It is possible to achieve validation by including
:on-reload
metadata in all my mount state definitions, but this ends up being a lot of boilerplate and dependent on me remembering to include it for every state; in addition, I don't feel comfortable having to include this in my production namespaces, when my initial call toinstrument
lives in a user namespace that is only loaded for development purposes.Is there any way around this problem?