0

I have the following code

# -*- coding: utf-8 -*-

# 好

##########################################

import time
from twisted.internet import reactor, threads
from twisted.web.server import Site, NOT_DONE_YET
from twisted.web.resource import Resource

##########################################

class Website(Resource):
  def getChild(self, name, request):
    return self
  def render(self, request):
    if request.path == "/sleep":
      duration = 3
      if 'duration' in request.args:
        duration = int(request.args['duration'][0])
      message = 'no message'
      if 'message' in request.args:
        message = request.args['message'][0]
      #-------------------------------------
      def deferred_activity():
        print 'starting to wait', message
        time.sleep(duration)
        request.setHeader('Content-Type', 'text/plain; charset=UTF-8')
        request.write(message)
        print 'finished', message
        request.finish()
      #-------------------------------------
      def responseFailed(err, deferred):
        pass; print err.getErrorMessage()
        deferred.cancel()
      #-------------------------------------
      def deferredFailed(err, deferred):
        pass; # print err.getErrorMessage()
      #-------------------------------------
      deferred = threads.deferToThread(deferred_activity)
      deferred.addErrback(deferredFailed, deferred) # will get called indirectly by responseFailed
      request.notifyFinish().addErrback(responseFailed, deferred) # to handle client disconnects
      #-------------------------------------
      return NOT_DONE_YET
    else:
      return 'nothing at', request.path

##########################################

reactor.listenTCP(321, Site(Website()))
print 'starting to serve'
reactor.run()

##########################################
# http://localhost:321/sleep?duration=3&message=test1
# http://localhost:321/sleep?duration=3&message=test2
##########################################

My issue is the following:

When I open two tabs in the browser, point one at http://localhost:321/sleep?duration=3&message=test1 and the other at http://localhost:321/sleep?duration=3&message=test2 (the messages differ) and reload the first tab and then ASAP the second one, then the finish almost at the same time. The first tab about 3 seconds after hitting F5, the second tab finishes about half a second after the first tab.

This is expected, as each request got deferred into a thread, and they are sleeping in parallel.

But when I now change the URL of the second tab to be the same as the one of the first tab, that is to http://localhost:321/sleep?duration=3&message=test1, then all this becomes blocking. If I press F5 on the first tab and as quickly as possible F5 on the second one, the second tab finishes about 3 seconds after the first one. They don't get executed in parallel.

As long as the entire URI is the same in both tabs, this server starts to block. This is the same in Firefox as well as in Chrome. But when I start one in Chrome and another one in Firefox at the same time, then it is non-blocking again.

So it may not neccessarily be related to Twisted, but maybe because of some connection reusage or something like that.

Anyone knows what is happening here and how I can solve this issue?

Daniel F
  • 13,684
  • 11
  • 87
  • 116

1 Answers1

1

Coincidentally, someone asked a related question over at the Tornado section. As you suspected, this is not an "issue" in Twisted but rather a "feature" of web browsers :). Tornado's FAQ page has a small section dedicated to this issue. The proposed solution is appending an arbitrary query string.

Quote of the day:

One dev's bug is another dev's undocumented feature!

Community
  • 1
  • 1
notorious.no
  • 4,919
  • 3
  • 20
  • 34