Merge lp:~free.ekanayaka/txlongpoll/frontend-ajax-move-inline-functions-to-methods into lp:txlongpoll

Proposed by Free Ekanayaka
Status: Merged
Approved by: Free Ekanayaka
Approved revision: 114
Merged at revision: 108
Proposed branch: lp:~free.ekanayaka/txlongpoll/frontend-ajax-move-inline-functions-to-methods
Merge into: lp:txlongpoll
Diff against target: 176 lines (+77/-67)
1 file modified
txlongpoll/frontend.py (+77/-67)
To merge this branch: bzr merge lp:~free.ekanayaka/txlongpoll/frontend-ajax-move-inline-functions-to-methods
Reviewer Review Type Date Requested Status
Alberto Donato (community) Approve
Review via email: mp+298282@code.launchpad.net

Commit message

Pure-refactoring branch, converting callbacks declared as inline functions to regular methods, for easier reading and isolation of local scope.

Description of the change

Pure-refactoring branch, converting callbacks declared as inline functions to regular methods, for easier reading and isolation of local scope.

To post a comment you must log in.
Revision history for this message
Alberto Donato (ack) wrote :

Looks good, +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'txlongpoll/frontend.py'
2--- txlongpoll/frontend.py 2016-06-06 13:07:31 +0000
3+++ txlongpoll/frontend.py 2016-06-24 08:25:34 +0000
4@@ -4,9 +4,10 @@
5 """
6 Async frontend server for serving answers from background processor.
7 """
8-
9 import json
10
11+from functools import partial
12+
13 from twisted.internet.defer import (
14 Deferred,
15 succeed,
16@@ -136,9 +137,12 @@
17 """
18 isLeaf = True
19
20- def __init__(self, message_queue):
21+ def __init__(self, source):
22+ """
23+ @param source: The NotificationSource to fetch notifications from.
24+ """
25 Resource.__init__(self)
26- self.message_queue = message_queue
27+ self.source = source
28 self._finished = {}
29
30 def render(self, request):
31@@ -150,7 +154,7 @@
32 """
33 if "uuid" not in request.args and "sequence" not in request.args:
34 request.setHeader("Content-Type", "text/plain")
35- return "Async frontend for %s" % self.message_queue._prefix
36+ return "Async frontend for %s" % self.source._prefix
37
38 if "uuid" not in request.args or "sequence" not in request.args:
39 request.setHeader("Content-Type", "text/plain")
40@@ -164,67 +168,73 @@
41 request.setResponseCode(BAD_REQUEST)
42 return "Invalid request"
43
44- request_id = "%s-%s" % (uuid, sequence)
45-
46- def _finished(ignored):
47- if request_id in self._finished:
48- # If the request_id is already in finished, that means the
49- # request terminated properly. We remove it from finished to
50- # prevent from it growing indefinitely.
51- self._finished.pop(request_id)
52- else:
53- # Otherwise, put it in finished so that the message is not sent
54- # when write is called.
55- self._finished[request_id] = True
56- self.message_queue.cancel_get_message(uuid, sequence)
57-
58- request.notifyFinish().addBoth(_finished)
59-
60- d = self.message_queue.get_message(uuid, sequence)
61-
62- def write(data):
63- result, tag = data
64- if self._finished.get(request_id):
65- self._finished.pop(request_id)
66- self.message_queue.reject_message(tag)
67- return
68-
69- self.message_queue.ack_message(tag)
70-
71- data = json.loads(result)
72-
73- if data.pop("original-uuid", None) == uuid:
74- # Ignore the message for the page who emitted the job
75- d = self.message_queue.get_message(uuid, sequence)
76- d.addCallback(write)
77- d.addErrback(failed)
78- return
79-
80- if "error" in data:
81- request.setResponseCode(BAD_REQUEST)
82-
83- request.setHeader("Content-Type", "application/json")
84-
85- request.write(result)
86- self._finished[request_id] = False
87- request.finish()
88-
89- def failed(error):
90- if self._finished.get(request_id):
91- self._finished.pop(request_id)
92- return
93-
94- if error.check(Timeout):
95- request.setResponseCode(REQUEST_TIMEOUT)
96- elif error.check(NotFound):
97- request.setResponseCode(NOT_FOUND)
98- else:
99- log.err(error, "Failed to get message")
100- request.setResponseCode(INTERNAL_SERVER_ERROR)
101- request.write(str(error.value))
102- self._finished[request_id] = False
103- request.finish()
104-
105- d.addCallback(write)
106- d.addErrback(failed)
107+ request.notifyFinish().addBoth(lambda _: self._done(uuid, sequence))
108+
109+ d = self.source.get_message(uuid, sequence)
110+ d.addCallback(partial(self._succeed, request, uuid, sequence))
111+ d.addErrback(partial(self._fail, request, uuid, sequence))
112 return NOT_DONE_YET
113+
114+ def _succeed(self, request, uuid, sequence, data):
115+ """Send a success notification to the client."""
116+ request_id = self._request_id(uuid, sequence)
117+ result, tag = data
118+ if self._finished.get(request_id):
119+ self._finished.pop(request_id)
120+ self.source.reject_message(tag)
121+ return
122+
123+ self.source.ack_message(tag)
124+
125+ data = json.loads(result)
126+
127+ if data.pop("original-uuid", None) == uuid:
128+ # Ignore the message for the page who emitted the job
129+ d = self.source.get_message(uuid, sequence)
130+ d.addCallback(partial(self._succeed, request, uuid, sequence))
131+ d.addErrback(partial(self._fail, request, uuid, sequence))
132+ return
133+
134+ if "error" in data:
135+ request.setResponseCode(BAD_REQUEST)
136+
137+ request.setHeader("Content-Type", "application/json")
138+
139+ request.write(result)
140+ self._finished[request_id] = False
141+ request.finish()
142+
143+ def _fail(self, request, uuid, sequence, error):
144+ """Send an error to the client."""
145+ request_id = self._request_id(uuid, sequence)
146+ if self._finished.get(request_id):
147+ self._finished.pop(request_id)
148+ return
149+
150+ if error.check(Timeout):
151+ request.setResponseCode(REQUEST_TIMEOUT)
152+ elif error.check(NotFound):
153+ request.setResponseCode(NOT_FOUND)
154+ else:
155+ log.err(error, "Failed to get message")
156+ request.setResponseCode(INTERNAL_SERVER_ERROR)
157+ request.write(str(error.value))
158+ self._finished[request_id] = False
159+ request.finish()
160+
161+ def _done(self, uuid, sequence):
162+ """Complete the request, doing the necessary bookkeeping."""
163+ request_id = self._request_id(uuid, sequence)
164+ if request_id in self._finished:
165+ # If the request_id is already in finished, that means the
166+ # request terminated properly. We remove it from finished to
167+ # prevent from it growing indefinitely.
168+ self._finished.pop(request_id)
169+ else:
170+ # Otherwise, put it in finished so that the message is not sent
171+ # when write is called.
172+ self._finished[request_id] = True
173+ self.source.cancel_get_message(uuid, sequence)
174+
175+ def _request_id(self, uuid, sequence):
176+ return "%s-%s" % (uuid, sequence)

Subscribers

People subscribed via source and target branches