Longpoll transport doesn't appear to honor request_timeout parameter
Hello,
i'm using crossbar in a web application that usually is configured to use websocket transport. Recently a client suffered of connection problems to the websocket transport endpoint caused by its company proxy configurations. While I try to better understand how to resolve this issue I tried to setup a workaround using longpoll transport. After battling with timeouts on the nginx proxy in front of the crossbar instance I stumbled upon an issue that seems caused by the crossbar server itself.
I set up the autobahn-js connection with 60 seconds (60000) request timeout to not have it interfere with the /lp/<session_id>/receive POST and and configured the transport in crossbar with the following parameters:
transports:
- type: web
endpoint:
type: tcp
port: 8082
paths:
/:
type: static
directory: /srv/app/www
lp:
type: longpoll
options:
request_timeout: 10
queue_limit_bytes: 0
queue_limit_messages: 0
session_timeout: 1800
but the effect is that the longpoll gets cancelled by the client running in the browser after 60 seconds. I've tried to understand and read the code pertaining to the transport to see if maybe it was the doc that was outdated and the parameter was renamend to something else. What i found is that the request_timeout is set here: https://github.com/crossbario/crossbar/blob/master/crossbar/router/longpoll.py#L620 in the WampLongPollResource initialization code but never used anywhere else in the code of the module. I don't know yet if it's read from other code or maybe used in twisted. I see special code to kill the session after the "session_timeout", but nothing for the single request.
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
Ah, the crossbar version I'm using is actually a 17.5.1
For the record, in the meantime I've overcome this bug by using a custom ping/pong to prevent reaching the client timeout
@azazel75 : can you post an example of your custom ping/pong behavior? I just discovered this same issue myself.
I'll also poke @crossbario to see if we can get someone's eye on this.
@markerikson as i've said, it is at the application level, on my customized "session" object:
PING_DELAY = 10 # secs
class Session:
...
@handler('on_pong')
def _on_pong_received(self):
self._last_ping = datetime.now()
if self.status == 'active':
self._ping_handle = self.loop.call_later(PING_DELAY, self._send_ping)
def _send_ping(self):
self.client.on_ping.notify()
all my code is using asyncio the @handler('on_pong') registers a subscription for an on_pong topic that schedules a publication for 10 secs from the event to the client.on_ping topic
@azazel75 : thanks for the fast response! Yeah, I just threw together something similar that publishes to a "keepalive" topic every 15 seconds, and set the AutobahnJS timeout to 45 seconds. Seems to be working for now. Still, annoying that that documented piece of functionality was never implemented.
I wish I had time to actually submit a PR that fixes the issue, but I'm swamped with actual work tasks atm.
@markerikson I do understand... at one point I was planning to rewrite the entire AutobahnJS in a pluggable way with ES6 because i don't need most of the cryptographic stuff (I use HAProxy in front of crossbar that takes care of encryption and i use anonymous connections) and also it doesn't play well with Sentry that we use for error collection, but I'm overwhelmed by other tasks too