From b23917dca0c531016ffb27f9136006497c987535 Mon Sep 17 00:00:00 2001 From: James Barnsley Date: Thu, 23 Jan 2020 06:57:52 +1300 Subject: [PATCH] Passing websocket/http ioloop through to iris core methods --- docker-compose.example.yml | 4 ++- docker/mopidy.example.conf | 7 +++- mopidy_iris/core.py | 19 ++++++++--- mopidy_iris/frontend.py | 4 +-- mopidy_iris/handlers.py | 68 ++++++++++++++++++++++++++++++++++---- mopidy_iris/system.py | 6 ++-- 6 files changed, 89 insertions(+), 19 deletions(-) diff --git a/docker-compose.example.yml b/docker-compose.example.yml index 3d06798f..b53506f2 100755 --- a/docker-compose.example.yml +++ b/docker-compose.example.yml @@ -19,7 +19,9 @@ services: - 6600:6600 - 6680:6680 volumes: - #- ./mopidy_iris:/iris/mopidy_iris (Uncomment this line to use a host-managed development build) + # Uncomment these lines to use a host-managed development build + #- ./mopidy_iris:/iris/mopidy_iris + #- ./IRIS_VERSION:/iris/IRIS_VERSION - ./docker/mopidy.conf:/config/mopidy.conf - HOST_MUSIC_DIRECTORY:/var/lib/mopidy/media - HOST_SNAPCAST_TEMP:/tmp diff --git a/docker/mopidy.example.conf b/docker/mopidy.example.conf index 73deffde..7f685911 100755 --- a/docker/mopidy.example.conf +++ b/docker/mopidy.example.conf @@ -9,4 +9,9 @@ output = audioresample ! audioconvert ! audio/x-raw,rate=48000,channels=2,format hostname = 0.0.0.0 [mpd] -hostname = 0.0.0.0 \ No newline at end of file +hostname = 0.0.0.0 + +[spotify] +# Fast startup because we use the Spotify HTTP API to load these instead +# Makes playlists unavailable under Browse > Spotify. +allow_playlists = false \ No newline at end of file diff --git a/mopidy_iris/core.py b/mopidy_iris/core.py index 89edd0a1..b7ddfff4 100755 --- a/mopidy_iris/core.py +++ b/mopidy_iris/core.py @@ -451,9 +451,10 @@ class IrisCore(pykka.ThreadingActor): ## def restart(self, *args, **kwargs): callback = kwargs.get('callback', False) + ioloop = kwargs.get('ioloop', False) # Trigger the action - IrisSystemThread('restart', self.restart_callback).start() + IrisSystemThread('restart', ioloop, self.restart_callback).start() self.broadcast(data={ 'method': "restart_started" @@ -490,13 +491,14 @@ class IrisCore(pykka.ThreadingActor): ## def upgrade(self, *args, **kwargs): callback = kwargs.get('callback', False) + ioloop = kwargs.get('ioloop', False) self.broadcast(data={ 'method': "upgrade_started" }) # Trigger the action - IrisSystemThread('upgrade', self.upgrade_callback).start() + IrisSystemThread('upgrade', ioloop, self.upgrade_callback).start() response = { 'message': "Upgrade started" @@ -532,9 +534,10 @@ class IrisCore(pykka.ThreadingActor): ## def local_scan(self, *args, **kwargs): callback = kwargs.get('callback', False) + ioloop = kwargs.get('ioloop', False) # Trigger the action - IrisSystemThread('local_scan', self.local_scan_callback).start() + IrisSystemThread('local_scan', ioloop, self.local_scan_callback).start() self.broadcast(data={ 'method': "local_scan_started" @@ -1109,6 +1112,7 @@ class IrisCore(pykka.ThreadingActor): ## def test(self, *args, **kwargs): callback = kwargs.get('callback', False) + ioloop = kwargs.get('ioloop', False) self.broadcast(data={ 'method': "test_started" @@ -1123,14 +1127,19 @@ class IrisCore(pykka.ThreadingActor): else: return response - IrisSystemThread('test', self.test_callback).run() + IrisSystemThread('test', ioloop, self.test_callback).run() - def test_callback(self, response, error): + def test_callback(self, response, error, update): if error: self.broadcast(data={ 'method': "test_error", 'params': error }) + elif error: + self.broadcast(data={ + 'method': "test_update", + 'params': update + }) else: self.broadcast(data={ 'method': "test_finished", diff --git a/mopidy_iris/frontend.py b/mopidy_iris/frontend.py index 6ba3362c..d1ae6263 100755 --- a/mopidy_iris/frontend.py +++ b/mopidy_iris/frontend.py @@ -1,8 +1,6 @@ +import pykka, logging, tornado from mopidy.core import CoreListener from .core import IrisCore - -import pykka -import logging from .mem import iris # import logger diff --git a/mopidy_iris/handlers.py b/mopidy_iris/handlers.py index 7bbfd251..446cf2ff 100755 --- a/mopidy_iris/handlers.py +++ b/mopidy_iris/handlers.py @@ -13,6 +13,7 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler): def initialize(self, core, config): self.core = core self.config = config + self.ioloop = tornado.ioloop.IOLoop.current() def check_origin(self, origin): return True @@ -68,9 +69,27 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler): # 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)) + await getattr(iris, message['method'])( + ioloop=self.ioloop, + data=params, + callback=lambda response, error=False: self.handle_result( + id=id, + method=message['method'], + response=response, + error=error + ) + ) else: - getattr(iris, message['method'])(data=params, callback=lambda response, error=False: self.handle_result(id=id, method=message['method'], response=response, error=error)) + getattr(iris, message['method'])( + ioloop=self.ioloop, + data=params, + callback=lambda response, error=False: self.handle_result( + id=id, + method=message['method'], + response=response, + error=error + ) + ) except Exception as e: logger.error(str(e)) @@ -133,6 +152,7 @@ class HttpHandler(tornado.web.RequestHandler): def initialize(self, core, config): self.core = core self.config = config + self.ioloop = tornado.ioloop.IOLoop.current() # Options request # This is a preflight request for CORS requests @@ -150,9 +170,27 @@ class HttpHandler(tornado.web.RequestHandler): # 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)) + await getattr(iris, slug)( + ioloop=self.ioloop, + request=self, + callback=lambda response, error=False: self.handle_result( + id=id, + method=slug, + response=response, + error=error + ) + ) else: - getattr(iris, slug)(request=self, callback=lambda response, error=False: self.handle_result(id=id, method=slug, response=response, error=error)) + getattr(iris, slug)( + ioloop=self.ioloop, + request=self, + callback=lambda response, error=False: self.handle_result( + id=id, + method=slug, + response=response, + error=error + ) + ) except Exception as e: logger.error(str(e)) @@ -174,9 +212,27 @@ class HttpHandler(tornado.web.RequestHandler): if hasattr(iris, slug): try: if asyncio.iscoroutinefunction(getattr(iris, slug)): - await getattr(iris, slug)(data=params, request=self.request, callback=lambda response=False, error=False: self.handle_result(id=id, method=slug, response=response, error=error)) + await getattr(iris, slug)( + data=params, + request=self.request, + callback=lambda response=False, error=False: self.handle_result( + id=id, + method=slug, + response=response, + error=error + ) + ) else: - getattr(iris, slug)(data=params, request=self.request, callback=lambda response=False, error=False: self.handle_result(id=id, method=slug, response=response, error=error)) + getattr(iris, slug)( + data=params, + request=self.request, + callback=lambda response=False, error=False: self.handle_result( + id=id, + method=slug, + response=response, + error=error + ) + ) except tornado.web.HTTPError as e: self.handle_result(id=id, error={'code': 32601, 'message': "Invalid JSON payload"}) diff --git a/mopidy_iris/system.py b/mopidy_iris/system.py index e2872f80..e4afc2e6 100755 --- a/mopidy_iris/system.py +++ b/mopidy_iris/system.py @@ -1,5 +1,5 @@ from threading import Thread -import logging, os, pathlib, subprocess, json, tornado, sys, shlex +import logging, os, pathlib, subprocess, json, sys # import logger logger = logging.getLogger(__name__) @@ -21,11 +21,11 @@ class IrisSystemPermissionError(IrisSystemError): class IrisSystemThread(Thread): _USE_SUDO = True - def __init__(self, action, callback): + def __init__(self, action, ioloop, callback): Thread.__init__(self) self.action = action self.callback = callback - self.ioloop = tornado.ioloop.IOLoop.current() + self.ioloop = ioloop self.script_path = pathlib.Path(__file__).parent / "system.sh" def get_command(self, action=None, *, non_interactive=False):