I’m trying to write a longpolling server with Twisted, but I’m afraid I’m not understanding the request management.
When the client navigates away from the page, I can see it continue to loop in the console. I thought the instance would just destroy itself when the client disconnects.
And that is my goal, I want to run the logic in DataService individually for each client that connects.
Here’s what I have: (i chopped this code down for easy consumption, might be some syntax errors because of that, but it came from working code)
class DataService(Resource):
def __init__(self, sid):
# set looping call
self.loopingCall = task.LoopingCall(self.__print_data)
self.loopingCall.start(5, False)
Resource.__init__(self)
self.sid = int(sid);
self.finished = False
# initialize response
self.response = response = {'status':1, 'message': 'OK', 'time':int(time.time()), 'data': {}}
def connectionLost(self, reason):
self.loopingCall.stop();
def render_GET(self, request):
# response will be json format
request.setHeader('Content-Type', 'application/json')
# make sure required GET vars exist
if 'lastupdate' not in request.args:
self.loopingCall.stop()
return ujson.dumps({'status':0,'message':'invalid query','data':{}})
# set last update timestamp from query string
self.lastupdate = int(request.args['lastupdate'][0])
# set self.request so we can access it in __print_data
self.request = request
# call print data
self.__print_data()
if not self.finished:
return server.NOT_DONE_YET
def __print_data(self):
# set updated data
if self.lastupdate < self.myappobj.lastupdate
self.response{'data']['items'] = {'foo':'bar'}
# if updates were found, close loop, print, and finish request
if len(response['data']) > 0:
self.loopingCall.stop()
self.request.write(self.jsonpcallback+'('+ujson.dumps(response)+')')
self.request.finish()
self.finished = True
class DataServer(Resource):
def getChild(self, sid, request):
return DataService(sid)
It doesn’t. First, instances are only destroyed when they are no longer “reachable” (just like any other kind of object you might have).
When you do this:
You’re creating a reference to
self.__print_data, which has a reference toself. TheLoopingCallthen registers itself with the reactor (when you start it). So now the reactor has an indirect reference toself. Soselfwill live forever, or until something changes.You can get the
LoopingCallto unregister itself from the reactor by stopping it. Once the reactor no longer refers to theLoopingCall, it will no longer be keeping theDataServiceinstance (self) alive.If you want to do this when the client closes the connection, then you want to use
Request.notifyFinish. This is covered in the Twisted documentation, but it’s pretty straightforward. You should do something like this:It’s an errback because you only care about the case where the client closes the connection, not the case where you close the connection.