Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Disable response timeout on websocket connections #2081

Merged
merged 5 commits into from
Mar 22, 2021

Conversation

ahopkins
Copy link
Member

Fixes #2078

This is only a bandaid. I think that when we address #2000 we might need to do something different here. Either incrementing the time or somehow merging the response timeout with the WEBSOCKET_PING_TIMEOUT.

@ahopkins ahopkins requested a review from a team as a code owner March 22, 2021 08:34
@ahopkins ahopkins marked this pull request as draft March 22, 2021 08:34
@ahopkins ahopkins added the needs tests PR that needs additional tests added label Mar 22, 2021
@codecov
Copy link

codecov bot commented Mar 22, 2021

Codecov Report

Merging #2081 (03509b6) into master (7be5f0e) will increase coverage by 0.011%.
The diff coverage is 100.000%.

Impacted file tree graph

@@              Coverage Diff              @@
##            master     #2081       +/-   ##
=============================================
+ Coverage   92.241%   92.253%   +0.011%     
=============================================
  Files           38        38               
  Lines         3480      3485        +5     
  Branches       582       583        +1     
=============================================
+ Hits          3210      3215        +5     
  Misses         183       183               
  Partials        87        87               
Impacted Files Coverage Δ
sanic/server.py 88.175% <100.000%> (+0.154%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7be5f0e...03509b6. Read the comment docs.

ashleysommer
ashleysommer previously approved these changes Mar 22, 2021
Copy link
Member

@ashleysommer ashleysommer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. I like the added debug messages too.
How can we add a test for this?

@ahopkins ahopkins marked this pull request as ready for review March 22, 2021 11:44
@ahopkins
Copy link
Member Author

ahopkins commented Mar 22, 2021

@ashleysommer This should do. It was interesting to me that using asyncio.sleep(2) would not work here. The test client kept blowing right over it. This is more indicative of the quirkiness of the test client than the response time out.

Here was the working example I also used to visually confirm this works (and breaks without the patch).

# server.py
from sanic import Sanic
from sanic.response import redirect

app = Sanic("websocket_example")
app.config.KEEP_ALIVE_TIMEOUT = 1
app.config.REQUEST_TIMEOUT = 1
app.config.RESPONSE_TIMEOUT = 10
app.config.WEBSOCKET_PING_INTERVAL = 1


@app.websocket("/feed")
async def feed(request, ws):
    while True:
        data = "pong"
        print("Sending: " + data)
        await ws.send(data)
        data = await ws.recv()
        print("Received: " + data)


app.static("/index.html", "./index.html")


@app.route("/")
def index(request):
    return redirect("/index.html")


if __name__ == "__main__":
    app.run(port=8001, debug=True)
<!-- index.html -->
<!DOCTYPE html>
<script>
    let ws
    let countforping = 0
    let countforpong = 0
    let waitingpong = false
    let running = false

    async function sleep(seconds = 1) {
        await new Promise(resolve => setTimeout(resolve, seconds * 1000));
    }

    async function pingPong() {
        log(".")
        if (countforping > 5) {
            log("sending ping")
            ws.send("ping")
            countforping = 0
            waitingpong = true
        }
        if (waitingpong) {
            countforpong += 1
        }
        if (countforpong > 3) {
            log("NO PONG")
            countforpong = 0
            waitingpong = false
            stop()
        }
        countforping += 1
        await sleep()
        if (running) {
            pingPong()
        }
    }

    function start() {
        ws = new WebSocket('ws://' + document.domain + ':' + location.port + '/feed')

        ws.onopen = async function (e) {
            log("Event: open")
            running = true
            await sleep(1)
            pingPong()
        }

        ws.onerror = function (e) {
            log("Event: error")
            console.log({readyState: this.readyState})
        }

        ws.onmessage = function (e) {
            log("Event: incoming: " + e.data)
            if (e.data === "pong") {
                waitingpong = false
                countforpong = 0
            }
        }
    }

    function stop() {
        ws.close()
        running = false
        log("ws.close()")
    }

    function log(msg) {
        console.log(msg)
        logElem.innerHTML += msg + "<br>"
        logElem.scrollTop = logElem.scrollHeight;
    }

    function reset() {
        document.querySelector("#logElem").innerHTML = ""
    }
</script>
<button onclick="start()">Start</button>
<button onclick="stop()">Stop</button>
<button onclick="reset()">Clear</button>
<pre id="logElem" style="margin: 6px 0; max-height: 600px; overflow-y: auto;"></pre>

@ahopkins ahopkins added release-needed and removed needs tests PR that needs additional tests added labels Mar 22, 2021
@ahopkins
Copy link
Member Author

Will merge and release after I have a closer look at #2079 and if it is something that needs to be addressed now.

@ahopkins ahopkins merged commit 4998fd5 into master Mar 22, 2021
@ahopkins ahopkins deleted the issue-2078-response-timeout-on-websocket branch March 22, 2021 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

websocket disconnect every minute and raise 503 error.
3 participants