Open vincentjames501 opened 5 years ago
An idea (though not bullet proof), we could make wrap-route-matches
return something synchronously like ::compojure/no-match
and tweak routes
like so?
(defn routes
"Create a Ring handler by combining several handlers into one."
[& handlers]
(fn
([request]
(apply compojure/routing request handlers))
([request respond raise]
(letfn [(f [handlers]
(loop [[handler & remaining-handlers] handlers]
(if handler
(let [respond' #(if % (respond %) (f remaining-handlers))]
(when (= (handler request respond' raise) ::compojure/no-route-found)
(recur remaining-handlers)))
(respond nil))))]
(f handlers)))))
It can technically still run into the same issues if lots of routes match though the chances are slim.
That's an interesting problem. As a temporary workaround, I'd suggest increasing the stack size for the running JVM, since you're not dealing with an unbounded stack.
Solving the problem in a more general way will require a bit of thought.
We have a large ring/compojure application with lots of api routes. We are trying to use ring's async handlers but we eventually run out of stack if a matching path is not found in time.
This is fine because it matches a route soon enough
The issue is that it will create a new entry in the stack for each handler that doesn't match:
Even if you break it into chunks like so, you still get the same error.
This can be rewritten using something like a go loop, but it's possible code is blocking and may unknowingly block peoples core async threads.
Any suggestions?