Question

Basically: Is there a way to tell (Python 2.7) when a socket times out if it is because nothing has been delivered to the socket or because the network connection is down?

I have a Python application that will connect to the Twitter Streaming API for long periods of time (>30 days). The app reads from the socket's buffer whenever a tweet is delivered but if no tweet is delivered the read command will timeout and throw an SSLError.

Here's a snippet where the reading/timeout happens:

    try:
        d = resp.read(1)
        return d
    except SSLError as e:
        # the read timed out, nothing was read
        return None
    except Exception as e:
        log.error('Error reading from stream : {0}'.format(e))

I set the timeout when creating the HTTPSConnection and currently it is set to 30 seconds. So if no tweet is read for 30 seconds, the resp.read command will timeout and throw the SSLError, so I ignore (by returning None, this is handled one level up from this snippet) and then read again for another 30 seconds. The problem is, if the network gets disconnected, even if it is reconnected shortly after, the socket doesn't ever seem to start reading again and just continues to time out. The only way to resolve this is to reconnect, which is fine because network disconnects are rare. I could set the timeout really high and just re-connect on every timeout but that increases the time my application isn't functioning just because someone yanked out a network cable. I could set the timeout low to minimize the downtime but then I am reconnecting needlessly when no tweets are read.

Is there a way to distinguish the reason based on the SSLError that is thrown?

Was it helpful?

Solution

OP here. Still don't know of a way to distinguish the reason for a timeout happening but I did manage to find something helpful in the Twitter Streaming Docs that manages to solve the root problem I had.

Stalls

If 90 seconds pass with no data received, including newlines, disconnect and reconnect immediately according to the backoff strategies in the next section. The Streaming API will send a keep-alive newline every 30 seconds to prevent your application from timing out the connection.

So basically, setting the timeout to a time larger than 30 seconds (Twitter recommends 90) will solve it because they will send a "heartbeat" every 30 seconds to assure the client that the streaming connection is still alive. Then whenever you do actually see a timeout, you can safely start the reconnection process.

Would still like to know if there's any sort of distinction within the SSLErrors but just in case anyone is experiencing the same issue I was I figured this might help.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top