Browse Source

Use async request for all api calls

pull/3356/head
Ruud 11 years ago
parent
commit
40f01dca6f
  1. 58
      couchpotato/api.py

58
couchpotato/api.py

@ -1,3 +1,5 @@
from functools import wraps
from threading import Thread
import json import json
import threading import threading
import traceback import traceback
@ -5,7 +7,6 @@ import urllib
from couchpotato.core.helpers.request import getParams from couchpotato.core.helpers.request import getParams
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from tornado.gen import coroutine
from tornado.web import RequestHandler, asynchronous from tornado.web import RequestHandler, asynchronous
@ -20,6 +21,24 @@ api_docs = {}
api_docs_missing = [] api_docs_missing = []
def run_async(func):
@wraps(func)
def async_func(*args, **kwargs):
func_hl = Thread(target = func, args = args, kwargs = kwargs)
func_hl.start()
return async_func
@run_async
def run_handler(route, kwargs, callback = None):
try:
res = api[route](**kwargs)
callback(res)
except:
log.error('Failed doing api request "%s": %s', (route, traceback.format_exc()))
callback({'success': False, 'error': 'Failed returning results'})
# NonBlock API handler # NonBlock API handler
class NonBlockHandler(RequestHandler): class NonBlockHandler(RequestHandler):
@ -65,7 +84,7 @@ def addNonBlockApiView(route, func_tuple, docs = None, **kwargs):
# Blocking API handler # Blocking API handler
class ApiHandler(RequestHandler): class ApiHandler(RequestHandler):
@coroutine @asynchronous
def get(self, route, *args, **kwargs): def get(self, route, *args, **kwargs):
route = route.strip('/') route = route.strip('/')
if not api.get(route): if not api.get(route):
@ -88,31 +107,40 @@ class ApiHandler(RequestHandler):
try: del kwargs['t'] try: del kwargs['t']
except: pass except: pass
# Fire api handler(s) # Add async callback handler
try: run_handler(route, kwargs, callback = self.taskFinished)
result = api[route](**kwargs)
except: except:
log.error('Failed doing api request "%s": %s', (route, traceback.format_exc())) log.error('Failed doing api request "%s": %s', (route, traceback.format_exc()))
result = {'success': False, 'error': 'Failed returning results'} self.write({'success': False, 'error': 'Failed returning results'})
self.finish()
api_locks[route].release()
post = get
def taskFinished(self, result):
if self.request.connection.stream.closed():
return
try:
# Check JSONP callback # Check JSONP callback
jsonp_callback = self.get_argument('callback_func', default = None) jsonp_callback = self.get_argument('callback_func', default = None)
if jsonp_callback: if jsonp_callback:
self.write(str(jsonp_callback) + '(' + json.dumps(result) + ')') self.write(str(jsonp_callback) + '(' + json.dumps(result) + ')')
self.set_header("Content-Type", "text/javascript") self.set_header("Content-Type", "text/javascript")
self.finish()
elif isinstance(result, tuple) and result[0] == 'redirect': elif isinstance(result, tuple) and result[0] == 'redirect':
self.redirect(result[1]) self.redirect(result[1])
else: else:
self.write(result) self.write(result)
self.finish()
except: except:
log.error('Failed doing api request "%s": %s', (route, traceback.format_exc())) log.debug('Failed doing request, probably already closed: %s', (traceback.format_exc()))
self.write({'success': False, 'error': 'Failed returning results'}) try: self.finish({'success': False, 'error': 'Failed returning results'})
except: pass
api_locks[route].release()
post = get
def addApiView(route, func, static = False, docs = None, **kwargs): def addApiView(route, func, static = False, docs = None, **kwargs):

Loading…
Cancel
Save