Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Cache restructure middleware args in HTTP endpoint macros #1400

Closed
wants to merge 45 commits into from

Conversation

frenchy64
Copy link
Contributor

@frenchy64 frenchy64 commented Dec 12, 2023

This is a followup to #1394 where we pushed all binding restructure middleware to the HTTP endpoint macros. It did not fix original problem of POST /bundle/import reevaluating its schema.

The HTTP endpoint macros reevaluate their arguments. This is by design, but very bad for performance. For example, the following benchmark simulates a route with a :body schema that takes 100ms (just an arbitrary round number) to evaluate/initialize. On master, 10 calls to this endpoint takes ~1030 ms. After this PR, it takes ~3ms.

(defn benchmark []
  (let [sleep (fn []
                (do (println "\tSleeping...")
                    (Thread/sleep 100)
                    (println "\tDone sleeping")))
        g (str (gensym))
        _ (println "vvvvvvvvvvvvvvvvvvvvvv")
        _ (println "Initializing route...")
        route (time
                (sut/POST "*" []
                          :body [body (do (sleep) s/Any)]
                          {:status 200
                           :body g}))
        _ (println "Done initializing route")
        _ (println "^^^^^^^^^^^^^^^^^^^^^^")]
    (println "vvvvvvvvvvvvvvvvvvvvvv")
    (println "Calling route...")
    (time
      (dotimes [i 10]
        (println "Call" i)
        (assert (= g (:body ((:handler route)
                             {:request-method :post :uri "/"}))))))
    (println "Done calling route")
    (println "^^^^^^^^^^^^^^^^^^^^^^"))
  :ok)

master bench result
Bench results for this PR included in the tests.

This PR rewrites compojure endpoint macro calls when it's safe. In particular, if the macro does not bind req like

(POST "" [] ...)

instead of

(POST "" req ...)

then we can rewrite args like

(POST "" [] :body [body SCHEMA] ...)

to

(let [s SCHEMA] (POST "" [] :body [body s] ...))

If it is not safe, then this PR throws a compile-time error and shows the user how to make the most performant endpoint. For example, if req is bound like here:

(ANY "*" req
     :body [body (->dynamic-schema)]
     {:status 200
      :body "hello"})

then the following error is thrown during expansion of ANY:

Please let-bind the :body schema like so:
(let [s# (->dynamic-schema)] (ANY "*" req :body [body s#] ...))

§ QA

No QA is needed.

§ Release Notes

intern: Cache restructure middleware args in HTTP endpoint macros

§ Squashed Commits

@frenchy64 frenchy64 changed the title WIP: Cache restructure middleware args in HTTP verbs WIP: Cache restructure middleware args in HTTP endpoint macros Dec 13, 2023
@frenchy64 frenchy64 changed the title WIP: Cache restructure middleware args in HTTP endpoint macros Cache restructure middleware args in HTTP endpoint macros Dec 13, 2023
@frenchy64 frenchy64 changed the title Cache restructure middleware args in HTTP endpoint macros WIP: Cache restructure middleware args in HTTP endpoint macros Dec 13, 2023
@frenchy64 frenchy64 closed this Jan 10, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant