mirror of
https://github.com/moparisthebest/SickRage
synced 2024-11-14 21:35:03 -05:00
Improved async threading code for WebUI
This commit is contained in:
parent
d2b6145f8c
commit
46bd600da0
@ -17,8 +17,8 @@
|
|||||||
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
|
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from __future__ import with_statement
|
from __future__ import with_statement
|
||||||
import threading
|
|
||||||
|
|
||||||
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
@ -75,11 +75,31 @@ except ImportError:
|
|||||||
|
|
||||||
from Cheetah.Template import Template
|
from Cheetah.Template import Template
|
||||||
|
|
||||||
|
from functools import wraps
|
||||||
from tornado.routes import route
|
from tornado.routes import route
|
||||||
from tornado.web import RequestHandler, authenticated, asynchronous
|
from tornado.web import RequestHandler, authenticated, asynchronous
|
||||||
|
|
||||||
from bug_tracker import BugTracker
|
from bug_tracker import BugTracker
|
||||||
|
|
||||||
|
route_locks = {}
|
||||||
|
|
||||||
|
def run_async(func):
|
||||||
|
@wraps(func)
|
||||||
|
def async_func(*args, **kwargs):
|
||||||
|
func_hl = threading.Thread(target = func, args = args, kwargs = kwargs)
|
||||||
|
func_hl.start()
|
||||||
|
|
||||||
|
return async_func
|
||||||
|
|
||||||
|
@run_async
|
||||||
|
def run_handler(route, kwargs, callback = None):
|
||||||
|
try:
|
||||||
|
res = route(**kwargs)
|
||||||
|
callback(res, route)
|
||||||
|
except:
|
||||||
|
logger.log('Failed doing api request "%s": %s' % (route, traceback.format_exc()), logger.ERROR)
|
||||||
|
callback({'success': False, 'error': 'Failed returning results'}, route)
|
||||||
|
|
||||||
def page_not_found(rh):
|
def page_not_found(rh):
|
||||||
index_url = sickbeard.WEB_ROOT
|
index_url = sickbeard.WEB_ROOT
|
||||||
url = rh.request.uri[len(index_url):]
|
url = rh.request.uri[len(index_url):]
|
||||||
@ -91,23 +111,6 @@ def page_not_found(rh):
|
|||||||
rh.set_status(404)
|
rh.set_status(404)
|
||||||
rh.write('Wrong API key used')
|
rh.write('Wrong API key used')
|
||||||
|
|
||||||
class Worker(threading.Thread):
|
|
||||||
def __init__(self, func, params=None, callback=None, *args, **kwargs):
|
|
||||||
super(Worker, self).__init__(*args, **kwargs)
|
|
||||||
self.callback = callback
|
|
||||||
self.func = func
|
|
||||||
self.params = params
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
# Get response
|
|
||||||
resp = self.func(**self.params)
|
|
||||||
if resp:
|
|
||||||
# Issue callback
|
|
||||||
try:
|
|
||||||
self.callback(ek.ss(resp).encode('utf-8', 'xmlcharrefreplace'))
|
|
||||||
except:
|
|
||||||
self.callback(resp)
|
|
||||||
|
|
||||||
class PageTemplate(Template):
|
class PageTemplate(Template):
|
||||||
def __init__(self, rh, *args, **kwargs):
|
def __init__(self, rh, *args, **kwargs):
|
||||||
kwargs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/", kwargs['file'])
|
kwargs['file'] = os.path.join(sickbeard.PROG_DIR, "gui/" + sickbeard.GUI_NAME + "/interfaces/default/", kwargs['file'])
|
||||||
@ -260,31 +263,52 @@ class WebHandler(BaseHandler):
|
|||||||
route = route.strip('/')
|
route = route.strip('/')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
route = getattr(self, route, self.index)
|
route = getattr(self, route)
|
||||||
if not callable(route):
|
|
||||||
self.set_status(404)
|
|
||||||
self.write('Could not load webui module')
|
|
||||||
return
|
|
||||||
except:
|
except:
|
||||||
page_not_found(self)
|
route = getattr(self, 'index')
|
||||||
return
|
|
||||||
|
# acquire route lock
|
||||||
|
route_locks[route] = threading.Lock()
|
||||||
|
route_locks[route].acquire()
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
# Sanitize argument lists:
|
# Sanitize argument lists:
|
||||||
params = self.request.arguments
|
kwargs = self.request.arguments
|
||||||
for arg, value in params.items():
|
for arg, value in kwargs.items():
|
||||||
if len(value) == 1:
|
if len(value) == 1:
|
||||||
params[arg] = value[0]
|
kwargs[arg] = value[0]
|
||||||
|
|
||||||
Worker(route, params, self.worker_done).start()
|
run_handler(route, kwargs, callback=self.taskFinished)
|
||||||
|
except:
|
||||||
|
route_locks[route].release()
|
||||||
|
page_not_found(self)
|
||||||
|
|
||||||
def worker_done(self, value):
|
def taskFinished(self, result, route):
|
||||||
try:
|
try:
|
||||||
self.write(value)
|
if result:
|
||||||
|
# encode result data
|
||||||
|
result = ek.ss(result).encode('utf-8', 'xmlcharrefreplace')
|
||||||
|
|
||||||
|
# Check JSONP callback
|
||||||
|
jsonp_callback = self.get_argument('callback_func', default=None)
|
||||||
|
|
||||||
|
if jsonp_callback:
|
||||||
|
self.write(str(jsonp_callback) + '(' + json.dumps(result) + ')')
|
||||||
|
self.set_header("Content-Type", "text/javascript")
|
||||||
|
self.finish()
|
||||||
|
else:
|
||||||
|
self.write(result)
|
||||||
|
self.finish()
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
logger.log('Failed proper encode: %s' % traceback.format_exc(), logger.ERROR)
|
||||||
except:
|
except:
|
||||||
logger.log("Failed doing web request '%s': %s" % (route, traceback.format_exc()), logger.ERROR)
|
logger.log("Failed doing web request '%s': %s" % (route, traceback.format_exc()), logger.ERROR)
|
||||||
self.write({'success': False, 'error': 'Failed returning results'})
|
try:self.finish({'success': False, 'error': 'Failed returning results'})
|
||||||
|
except:pass
|
||||||
|
|
||||||
self.finish()
|
# release route lock
|
||||||
|
route_locks[route].release()
|
||||||
|
|
||||||
# link post to get
|
# link post to get
|
||||||
post = get
|
post = get
|
||||||
|
@ -12,6 +12,7 @@ from tornado.httpserver import HTTPServer
|
|||||||
from tornado.ioloop import IOLoop
|
from tornado.ioloop import IOLoop
|
||||||
from tornado.routes import route
|
from tornado.routes import route
|
||||||
|
|
||||||
|
|
||||||
class MultiStaticFileHandler(StaticFileHandler):
|
class MultiStaticFileHandler(StaticFileHandler):
|
||||||
def initialize(self, paths, default_filename=None):
|
def initialize(self, paths, default_filename=None):
|
||||||
self.paths = paths
|
self.paths = paths
|
||||||
@ -101,9 +102,10 @@ class SRWebServer(threading.Thread):
|
|||||||
self.app.add_handlers(".*$", [
|
self.app.add_handlers(".*$", [
|
||||||
(r'%s(/?)' % self.options['api_root'], ApiHandler),
|
(r'%s(/?)' % self.options['api_root'], ApiHandler),
|
||||||
(r'%s/getkey(/?)' % self.options['web_root'], KeyHandler),
|
(r'%s/getkey(/?)' % self.options['web_root'], KeyHandler),
|
||||||
(r'%s/api/builder' % self.options['web_root'], RedirectHandler, {"url": self.options['web_root'] + '/apibuilder/'}),
|
(r'%s/api/builder' % self.options['web_root'], RedirectHandler,
|
||||||
|
{"url": self.options['web_root'] + '/apibuilder/'}),
|
||||||
(r'%s/login(/?)' % self.options['web_root'], LoginHandler),
|
(r'%s/login(/?)' % self.options['web_root'], LoginHandler),
|
||||||
(r'%s/logout(/?)' % self.options['web_root'], LogoutHandler)
|
(r'%s/logout(/?)' % self.options['web_root'], LogoutHandler),
|
||||||
] + route.get_routes())
|
] + route.get_routes())
|
||||||
|
|
||||||
# Static Path Handlers
|
# Static Path Handlers
|
||||||
|
Loading…
Reference in New Issue
Block a user