Browse code
made the server more asynchronous
Ed L authored on 17/10/2011 17:54:41
Showing 1 changed files
Showing 1 changed files
... | ... |
@@ -37,6 +37,7 @@ import jsonrpc.common |
37 | 37 |
# Twisted imports |
38 | 38 |
from twisted.web import server |
39 | 39 |
from twisted.internet import threads |
40 |
+from twisted.internet import defer |
|
40 | 41 |
from twisted.web.resource import Resource |
41 | 42 |
|
42 | 43 |
|
... | ... |
@@ -119,7 +120,7 @@ class JSON_RPC(Resource): |
119 | 120 |
self._ebRender(e, request, content.id if hasattr(content, 'id') else None) |
120 | 121 |
|
121 | 122 |
else: |
122 |
- d = threads.deferToThread(self._action, request, content) |
|
123 |
+ d = self._action(request, content) |
|
123 | 124 |
d.addCallback(self._cbRender, request) |
124 | 125 |
d.addErrback(self._ebRender, request, content.id if hasattr(content, 'id') else None) |
125 | 126 |
except BaseException, e: |
... | ... |
@@ -135,27 +136,42 @@ class JSON_RPC(Resource): |
135 | 136 |
|
136 | 137 |
if contents == []: raise jsonrpc.common.InvalidRequest |
137 | 138 |
|
139 |
+ def callmethod(request, rpcrequest, add, **kwargs): |
|
140 |
+ add.update(kwargs) |
|
141 |
+ result = self.eventhandler.callmethod(request, rpcrequest, **add) |
|
142 |
+ return result |
|
143 |
+ |
|
144 |
+ deferreds = [] |
|
138 | 145 |
for rpcrequest in contents: |
139 | 146 |
res = None |
147 |
+ add = copy.deepcopy(rpcrequest.extra) |
|
148 |
+ add.update(kw) |
|
149 |
+ deferreds.append(threads.deferToThread(callmethod, request, rpcrequest, add)) |
|
150 |
+ deferreds = defer.DeferredList(deferreds, consumeErrors=True) |
|
151 |
+ |
|
152 |
+ @deferreds.addCallback |
|
153 |
+ def helper(deferredresults): |
|
154 |
+ result = [] |
|
155 |
+ for success, methodresult in deferredresults: |
|
156 |
+ res = None |
|
157 |
+ if success: |
|
158 |
+ res = jsonrpc.common.Response(id=rpcrequest.id, result=methodresult) |
|
159 |
+ res = self.eventhandler.processrequest(res, request.args, **kw) |
|
160 |
+ else: |
|
161 |
+ try: |
|
162 |
+ methodresult.raiseException() |
|
163 |
+ except Exception, e: |
|
164 |
+ res = self.render_error(e, rpcrequest.id) |
|
140 | 165 |
|
141 |
- try: |
|
142 |
- add = copy.deepcopy(rpcrequest.extra) |
|
143 |
- add.update(kw) |
|
144 |
- res = jsonrpc.common.Response(id=rpcrequest.id, result=self.eventhandler.callmethod(request, rpcrequest, **add)) |
|
145 |
- res = self.eventhandler.processrequest(res, request.args, **kw) |
|
146 |
- except Exception, e: |
|
147 |
- res = self.render_error(e, rpcrequest.id) |
|
148 |
- |
|
149 |
- if res.id is not None: |
|
150 |
- result.append(res) |
|
151 |
- |
|
152 |
- |
|
166 |
+ if res.id is not None: |
|
167 |
+ result.append(res) |
|
153 | 168 |
|
154 |
- if result != []: |
|
155 |
- if not islist: result = result[0] |
|
156 |
- else: result = None |
|
169 |
+ if result != []: |
|
170 |
+ if not islist: result = result[0] |
|
171 |
+ else: result = None |
|
172 |
+ return result |
|
157 | 173 |
|
158 |
- return result |
|
174 |
+ return deferreds |
|
159 | 175 |
|
160 | 176 |
|
161 | 177 |
def _setresponseCode(self, result, request): |
... | ... |
@@ -166,32 +182,38 @@ class JSON_RPC(Resource): |
166 | 182 |
request.setResponseCode(code) |
167 | 183 |
|
168 | 184 |
def _cbRender(self, result, request): |
169 |
- self._setresponseCode(result, request) |
|
170 |
- self.eventhandler.log(result, request, error=False) |
|
171 |
- if result is not None: |
|
172 |
- request.setHeader("content-type", 'application/json') |
|
173 |
- result = jsonrpc.jsonutil.encode(result).encode('utf-8') |
|
174 |
- request.setHeader("content-length", len(result)) |
|
175 |
- request.write(result) |
|
176 |
- request.finish() |
|
185 |
+ @threads.deferToThread |
|
186 |
+ def _inner(*args, **_): |
|
187 |
+ self._setresponseCode(result, request) |
|
188 |
+ self.eventhandler.log(result, request, error=False) |
|
189 |
+ if result is not None: |
|
190 |
+ request.setHeader("content-type", 'application/json') |
|
191 |
+ result_ = jsonrpc.jsonutil.encode(result).encode('utf-8') |
|
192 |
+ request.setHeader("content-length", len(result_)) |
|
193 |
+ request.write(result_) |
|
194 |
+ request.finish() |
|
195 |
+ return _inner |
|
177 | 196 |
|
178 | 197 |
def _ebRender(self, result, request, id, finish=True): |
179 |
- err = None |
|
180 |
- if not isinstance(result, BaseException): |
|
181 |
- try: result.raiseException() |
|
182 |
- except BaseException, e: |
|
183 |
- err = e |
|
184 |
- self.eventhandler.log(err, request, error=True) |
|
185 |
- else: err = result |
|
186 |
- |
|
187 |
- err = self.render_error(err, id) |
|
188 |
- self._setresponseCode(err, request) |
|
189 |
- |
|
190 |
- request.setHeader("content-type", 'application/json') |
|
191 |
- result = jsonrpc.jsonutil.encode(err).encode('utf-8') |
|
192 |
- request.setHeader("content-length", len(result)) |
|
193 |
- request.write(result) |
|
194 |
- if finish: request.finish() |
|
198 |
+ @threads.deferToThread |
|
199 |
+ def _inner(*args, **_): |
|
200 |
+ err = None |
|
201 |
+ if not isinstance(result, BaseException): |
|
202 |
+ try: result.raiseException() |
|
203 |
+ except BaseException, e: |
|
204 |
+ err = e |
|
205 |
+ self.eventhandler.log(err, request, error=True) |
|
206 |
+ else: err = result |
|
207 |
+ |
|
208 |
+ err = self.render_error(err, id) |
|
209 |
+ self._setresponseCode(err, request) |
|
210 |
+ |
|
211 |
+ request.setHeader("content-type", 'application/json') |
|
212 |
+ result_ = jsonrpc.jsonutil.encode(err).encode('utf-8') |
|
213 |
+ request.setHeader("content-length", len(result_)) |
|
214 |
+ request.write(result_) |
|
215 |
+ if finish: request.finish() |
|
216 |
+ return _inner |
|
195 | 217 |
|
196 | 218 |
|
197 | 219 |
def render_error(self, e, id): |