metosin / reitit

A fast data-driven routing library for Clojure/Script

Home Page:https://cljdoc.org/d/metosin/reitit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Default printing when coercion fails is very expensive

bsless opened this issue · comments

While reitit is fast in its happy path, when coercion fails there are several paths which are extremely wasteful:

In coercion.cljc:

(defn ^:no-doc response-coercion-failed! [result coercion value request response]
  (throw
   (ex-info
    (str "Response coercion failed: " (pr-str result))
    (merge
     (into {} result)
     {:type ::response-coercion
      :coercion coercion
      :value value
      :in [:response :body]
      :request request
      :response response}))))

pr-str serializes the entire result which might be very large

In reitit/coercion/malli

       (-encode-error [_ error]
         (cond-> error
           (show? :humanized) (assoc :humanized (me/humanize error {:wrap :message}))
           (show? :schema) (update :schema edn/write-string opts)
           (show? :errors) (-> (me/with-error-messages opts)
                               (update :errors (partial map #(update % :schema edn/write-string opts))))

returning the schema and errors by default and serializing them to edn string is also very slow and expensive.

Should these be off by default?

I think they should. It's a breaking change, but for the better.

So proposed changes:

  • remove :schema and :errors from default coercion error keys
  • don't pr-str result in {response,request}-coercion-failed! by default, add option to do so?

@ikitommi Opened a PR to fix those two issues, also unrolled the merge on error, wdyt?