100% with you. That's why I wrote it isn't "really" possible. It is possible, just under limited conditions. IIRC, one could also use the COMET chunking technique to faciliate this - though that would likely cause some client side issues. If you're doing a direct browser-to-server connection, one can somewhat monitor the situation as you described - but most deployments use proxies, gateways, load balancers, wsgi, etc. It's also possible the client has an open connection / keepalive into your LAN, but one of the services on your network timed out and "dropped" the connection. From the user's vantage, the connection is active; but from the server's vantage it's dropped.
In any event, my point should have been more clear: "Detecting client disconnects" isn't a **standard** concept across any web frameworks or technologies, and this isn't a deficiency of Pyramid. It's possible to somewhat detect, but it's not something I've ever seen natively supported in a framework - whether it's Python, Go, C, Java, Ruby, PHP, etc - because of how applications are often deployed in layered environments. On Tuesday, March 8, 2022 at 10:28:05 PM UTC-5 Bert JW Regeer wrote: > I would disagree with this statement, but only narrowly, once you start > talking about proxies and reverse proxies and things of that nature, it > becomes much harder because the client isn’t directly connected anymore. In > most of todays environments you are right that it is really hard to know if > a remote client went away or if a request was actually successfully > returned to the remote client (and not just any intermediary > proxies/servers that may be buffering the request). > > It is hard to do in Python based threaded servers because even though the > code is running in a thread, and the main thread knows about the connection > being dropped, there’s no way for the main thread to cancel the running of > the worker thread and notify it. pthread_cancel does not work, and there is > no good way to signal to the thread to stop running code or to interrupt > it, especially during heavy computation. HTTP/1.1 also makes this somewhat > more difficult, in that the only way for the main thread to know is to > continue telling the kernel it wants to read from the socket the client is > connected on, with HTTP pipelining the client can send multiple requests at > once, and we’d have to buffer those requests, otherwise the call to > select()/poll() becomes a busy loop because each time we call > select()/poll() the OS would tell us the socket is ready for reading. > Thankfully HTTP pipelining these days is very rare because of incredibly > poor support for having multiple requests in flight, while the response > being returned would close the connection due to an error (the client would > have to retry any in-flight requests that were pipelined but not replied > to). > > You can emulate it somewhat by checking to see during various points of > computation whether the client has gone away, and then manually acting upon > it, and waitress has support for that. It is not enabled by default because > of the HTTP pipelining issue, and the issue of spinning on select(), but it > is configurable to attempt to buffer up to X requests by setting the flag > `channel_request_lookahead` to something that is non-zero. > > There’s just no predefined way to do it across WSGI servers, nor does > pyramid_tm provide any helpers for it since it can’t add those checks for > you as you are generating your response. This is a waitress extension. > > The feature was introduced in this PR: > > https://github.com/Pylons/waitress/pull/310 > > I don’t think there’s good example of how to use it in the documentation, > but here’s a quick and dirty example: > > import logging > import time > > log = logging.getLogger(__name__) > > > def application(environ, start_response): > check = environ["waitress.client_disconnected"] > > for i in range(10): > # do some computation > log.debug("Starting computation for %d", i) > time.sleep(2) > log.debug("Completed computation for %d", i) > > if check(): > log.debug("Remote client went away, processed %d items", i + 1) > break > > start_response( > "200 OK", > [ > ("Content-Type", "application/octet-stream"), > ], > ) > > return [b"work completed"] > > > if __name__ == "__main__": > import waitress > > logging.basicConfig( > format="%(asctime)-15s %(levelname)-8s %(name)s %(message)s", > level=logging.DEBUG, > ) > > waitress.serve(application, channel_request_lookahead=5) > > Now start this process, and then run curl but hit Ctrl + C on curl a > second or two after you start curl: > > You should see something like the following: > > python client_disconnected.py > 2022-03-08 20:12:01,081 INFO waitress Serving on http://0.0.0.0:8080 > 2022-03-08 20:12:04,206 DEBUG __main__ Starting computation for 0 > 2022-03-08 20:12:06,211 DEBUG __main__ Completed computation for 0 > 2022-03-08 20:12:06,211 DEBUG __main__ Starting computation for 1 > 2022-03-08 20:12:08,215 DEBUG __main__ Completed computation for 1 > 2022-03-08 20:12:08,216 DEBUG __main__ Remote client went away, processed > 2 items > 2022-03-08 20:12:08,217 INFO waitress Client disconnected while serving / > > An app developer who knows that the clients are always going to be > directly connected, can add code similar to the above in their response > code and do these checks manually during their computation, and if they > raise an error, pyramid_tm will appropriate abort the transaction, and > pyramid should run the exception view machinery (although that response > will never make it back to the client, it should be possible to use it at > that point to do any extra cleanup or whatnot though) > > Hopefully Andrew Free this helps somewhat, in that it is possible, it’s > just extra code you have to write and be aware of, it is not something that > comes for free, and requires that you use waitress, and it requires that > you set the `channel_request_lookhead` flag, and it requires that you know > your clients are directly connected. > > Caveat emptor. > > Thanks, > Bert JW Regeer > > > On Mar 7, 2022, at 13:05, Jonathan Vanasco <jvan...@gmail.com> wrote: > > > > Just to clarify the above comment, this concept isn't really possible > with any internet technology in general, not just Pyramid. > > On Thursday, February 17, 2022 at 8:35:25 PM UTC-5 Bert JW Regeer wrote: > > No, this is not possible *. > > > > * Except under some very narrow circumstances, but none that are easy to > use or directly supported in Pyramid > > > >> On Feb 17, 2022, at 13:12, Andrew Free <andrew...@gmail.com> wrote: > >> > >> Is there a way to subscribe to any events of a dropped/lost connection? > >> > >> For example, if the user closed the browser window in the middle of a > request. I am using pyramid_tm and having a hard time finding a method for > this. I just want to run some code based on the request object state in the > event that the response doesn't make it back to the client and the > transaction does not complete. I've looked into the exception_view_config > and this doesn't appear to help. Would a tween be the best way to handle > this? > >> Thanks. > >> > >> > >> -- > >> You received this message because you are subscribed to the Google > Groups "pylons-discuss" group. > >> To unsubscribe from this group and stop receiving emails from it, send > an email to pylons-discus...@googlegroups.com. > >> To view this discussion on the web visit > https://groups.google.com/d/msgid/pylons-discuss/cab03e28-c370-4dcb-917a-7b5d36e7a86fn%40googlegroups.com > . > > > > > > -- > > You received this message because you are subscribed to the Google > Groups "pylons-discuss" group. > > To unsubscribe from this group and stop receiving emails from it, send > an email to pylons-discus...@googlegroups.com. > > To view this discussion on the web visit > https://groups.google.com/d/msgid/pylons-discuss/113341b5-529b-4bb8-b1e8-5a3d28ce028dn%40googlegroups.com > . > > -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To unsubscribe from this group and stop receiving emails from it, send an email to pylons-discuss+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/pylons-discuss/d2f50f9a-1510-4e08-a49d-b0fd405cba1dn%40googlegroups.com.