0

Is there any way to make requests to my server automatically time out (on the server) after X seconds?

I want to do this because on heroku requests time out after 30 seconds, and I don't want to waste server resources on computing responses in these cases. I also want to kill any db transactions that are open, so I don't change the database without the user getting a decent response.

I'm using HTTP-kit 2.3.0 and compojure 1.6.1.

(I know that having requests take this long is not best practice but this is for a backoffice project, and these things happen for instance when the DB becomes unreachable)

rutchkiwi
  • 427
  • 3
  • 14

1 Answers1

0

Killing DB transactions is not trivial. If the JDBC driver is trying to connect to a DB and is waiting for the DB server to respond, you can try to configure that timeout in the JDBC driver properties.

Otherwise you would have to try to kill a blocked thread in Java, which is not possible. You can try to interrupt it, but there's no guarantee that will interrupt all the way to the ring handler.

If you use the HTTPKit API directly (i.e. not using ring), you could send a response after a timeout (using core.async, for example). An example of that can be found here: https://www.braveclojure.com/core-async/

Support for async ring is in progress for HTTPKit https://github.com/http-kit/http-kit/issues/394 (The Ring 2 specification is WIP as well)

If you need a solution now, you could try Aleph instead. That gives you the convenience of Ring handlers, but also allows you to create a response asynchronously. https://github.com/ztellman/aleph

(there might be more alternatives. Vert.x comes to mind. Maybe other Clojure alternatives too)

Jochen Bedersdorfer
  • 4,093
  • 24
  • 26
  • Hmm I believe an interrupt would work in my case - but how would I go about to do that? – rutchkiwi Apr 09 '20 at 18:19
  • interrupt requires two threads: one that does the work and the other taking care of timeouts and interrupts accordingly. It is not recommended to go down this path as you don't know if the JDBC drivers will honor the call (or re-try themselves etc.) – Jochen Bedersdorfer Apr 09 '20 at 21:13
  • JDBC (so far) is blocking by nature and no amount of "asynchronicity" (like Aleph) around that will help you. There's standard JDBC Statement.cancel method which they could use; or just try to interrupt - a driver can catch that exception but it's easy enough to try, – Juraj Martinka Apr 10 '20 at 04:18
  • Yes, everyone understands it is blocking. Doesn't mean you can't provide timeouts on the ring handler level. Interrupt and cancel both come with no guarantees, thus using an async web server that doesn't have to tie the thread that handles the request with the thread pool handling JDBC calls. You can also that with a blocking http server, but you are reducing availability that way. Source: wrote an async Postgres driver once – Jochen Bedersdorfer Apr 10 '20 at 05:13