Moving away from threads, using async instead for system tasks; local scan not working any more

This commit is contained in:
James Barnsley
2020-01-01 12:13:18 +13:00
parent 7b97d3a603
commit e6136505b4
5 changed files with 70 additions and 85 deletions

View File

@ -1 +1 @@
3.43.0
3.44.0

View File

@ -452,68 +452,58 @@ class IrisCore(pykka.ThreadingActor):
# Restart Mopidy
# This requires sudo access to system.sh
##
def restart(self, *args, **kwargs):
async def restart(self, *args, **kwargs):
callback = kwargs.get('callback', False)
# Trigger the action
IrisSystemThread('restart', self.restart_callback).start()
self.broadcast(data={
'method': "restart_started"
})
response = {
'message': "Restart started"
}
if (callback):
callback(response)
else:
return response
callback({
'message': "Restarting..."
})
def restart_callback(self, response, error):
if error:
task_response = await IrisSystemThread('restart').run()
if 'error' in task_response:
self.broadcast(data={
'method': "restart_error",
'params': error
'params': task_response
})
else:
self.broadcast(data={
'method': "restart_finished"
'method': "restart_finished",
'params': task_response
})
##
# Run an upgrade of Iris
##
def upgrade(self, *args, **kwargs):
async def upgrade(self, *args, **kwargs):
callback = kwargs.get('callback', False)
self.broadcast(data={
'method': "upgrade_started"
})
# Trigger the action
IrisSystemThread('upgrade', self.upgrade_callback).start()
response = {
'message': "Upgrade started"
}
if (callback):
callback(response)
else:
return response
callback({
'message': "Upgrade started"
})
task_response = await IrisSystemThread('upgrade').run()
def upgrade_callback(self, response, error):
if error:
if 'error' in task_response:
self.broadcast(data={
'method': "upgrade_error",
'params': error
'params': task_response
})
else:
self.broadcast(data={
'method': "upgrade_finished",
'params': response
'params': task_response
})
self.restart()
@ -525,31 +515,26 @@ class IrisCore(pykka.ThreadingActor):
async def local_scan(self, *args, **kwargs):
callback = kwargs.get('callback', False)
# Trigger the action
await IrisSystemThread('local_scan', self.local_scan_callback).start()
self.broadcast(data={
'method': "local_scan_started"
})
response = {
'message': "Local scan started"
}
if (callback):
callback(response)
else:
return response
callback({
'message': "Local scan started"
})
task_response = await IrisSystemThread('local_scan').run()
def local_scan_callback(self, response, error):
if error:
if 'error' in task_response:
self.broadcast(data={
'method': "local_scan_error",
'params': error
'params': task_response
})
else:
self.broadcast(data={
'method': "local_scan_finished",
'params': response
'params': task_response
})
@ -988,7 +973,7 @@ class IrisCore(pykka.ThreadingActor):
try:
http_client = tornado.httpclient.HTTPClient()
request = tornado.httpclient.HTTPRequest(url, method='POST', body=urllib.urlencode(data))
request = tornado.httpclient.HTTPRequest(url, method='POST', body=urllib.parse.urlencode(data))
response = http_client.fetch(request)
token = json.loads(response.body)
@ -1085,33 +1070,27 @@ class IrisCore(pykka.ThreadingActor):
##
# Simple test method. Not for use in production for any purposes.
##
def test(self, *args, **kwargs):
async def test(self, *args, **kwargs):
callback = kwargs.get('callback', False)
self.broadcast(data={
'method': "test_started"
})
# Trigger the action
IrisSystemThread('test', self.test_callback).start()
response = {
'message': "Running test... please wait"
}
if (callback):
callback(response)
else:
return response
callback({
'message': "Running test... please wait"
})
def test_callback(self, response, error):
if error:
task_response = await IrisSystemThread('test').run()
if 'error' in task_response:
self.broadcast(data={
'method': "test_error",
'params': error
'params': task_response
})
else:
self.broadcast(data={
'method': "test_finished",
'params': response
'params': task_response
})

View File

@ -67,6 +67,8 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler):
# make sure the method exists
if hasattr(iris, message['method']):
try:
# For async methods we need to await, but it must be ommited for syncronous methods
if asyncio.iscoroutinefunction(getattr(iris, message['method'])):
await getattr(iris, message['method'])(data=params, callback=lambda response, error=False: self.handle_result(id=id, method=message['method'], response=response, error=error))
else:
@ -147,6 +149,8 @@ class HttpHandler(tornado.web.RequestHandler):
# make sure the method exists
if hasattr(iris, slug):
try:
# For async methods we need to await, but it must be ommited for syncronous methods
if asyncio.iscoroutinefunction(getattr(iris, slug)):
await getattr(iris, slug)(request=self, callback=lambda response, error=False: self.handle_result(id=id, method=slug, response=response, error=error))
else:

View File

@ -1,21 +1,19 @@
from threading import Thread
import os, logging, subprocess, json
import os, logging, subprocess, json, asyncio
# import logger
logger = logging.getLogger(__name__)
class IrisSystemThread(Thread):
def __init__(self, action, callback):
Thread.__init__(self)
class IrisSystemThread:
def __init__(self, action):
self.action = action
self.callback = callback
self.path = os.path.dirname(__file__)
##
# Run the defined action
##
def run(self):
async def run(self):
logger.info("Running system action '"+self.action+"'")
try:
@ -27,23 +25,29 @@ class IrisSystemThread(Thread):
'message': "Permission denied",
'description': str(e)
}
if self.callback:
self.callback(False, error)
return
# Run the actual task (this is the process-blocking instruction)
output = subprocess.check_output([self.path+"/system.sh "+self.action], shell=True)
logger.debug("System action '"+self.action+"' completed with output:")
logger.debug(output)
# And then, when complete, return to our callback
if self.callback:
response = {
'output': str(output)
return {
'error': error
}
logger.debug("sudo "+ self.path +"/system.sh "+ self.action)
proc = subprocess.Popen(["sudo", self.path+"/system.sh", self.action],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
stdout,stderr = proc.communicate()
if stderr:
logger.error(stderr.decode())
return {
'error': stderr.decode()
}
else:
logger.info(stdout.decode())
return {
'output': stdout.decode()
}
self.callback(response, False)
##

View File

@ -1,7 +1,5 @@
#!/bin/bash
echo -e "Running $1 yeah nah"
if [[ "$(pwd)" = "/iris/mopidy_iris/system.sh" ]]; then
IS_CONTAINER=true
else
@ -34,9 +32,9 @@ elif [[ $1 = "local_scan" ]]; then
elif [[ $1 = "test" ]]; then
sleep 3
sleep 5
TEST="$(echo 'Hello, this is your bash speaking. I was sleeping for 3 seconds.')"
TEST="$(echo 'Hello, this is your bash speaking. I was sleeping for 5 seconds.')"
echo -e "${TEST}"
else