Passing websocket/http ioloop through to iris core methods

This commit is contained in:
James Barnsley
2020-01-23 06:57:52 +13:00
parent 7bbf9621ab
commit b23917dca0
6 changed files with 89 additions and 19 deletions

View File

@ -19,7 +19,9 @@ services:
- 6600:6600 - 6600:6600
- 6680:6680 - 6680:6680
volumes: 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 - ./docker/mopidy.conf:/config/mopidy.conf
- HOST_MUSIC_DIRECTORY:/var/lib/mopidy/media - HOST_MUSIC_DIRECTORY:/var/lib/mopidy/media
- HOST_SNAPCAST_TEMP:/tmp - HOST_SNAPCAST_TEMP:/tmp

View File

@ -10,3 +10,8 @@ hostname = 0.0.0.0
[mpd] [mpd]
hostname = 0.0.0.0 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

View File

@ -451,9 +451,10 @@ class IrisCore(pykka.ThreadingActor):
## ##
def restart(self, *args, **kwargs): def restart(self, *args, **kwargs):
callback = kwargs.get('callback', False) callback = kwargs.get('callback', False)
ioloop = kwargs.get('ioloop', False)
# Trigger the action # Trigger the action
IrisSystemThread('restart', self.restart_callback).start() IrisSystemThread('restart', ioloop, self.restart_callback).start()
self.broadcast(data={ self.broadcast(data={
'method': "restart_started" 'method': "restart_started"
@ -490,13 +491,14 @@ class IrisCore(pykka.ThreadingActor):
## ##
def upgrade(self, *args, **kwargs): def upgrade(self, *args, **kwargs):
callback = kwargs.get('callback', False) callback = kwargs.get('callback', False)
ioloop = kwargs.get('ioloop', False)
self.broadcast(data={ self.broadcast(data={
'method': "upgrade_started" 'method': "upgrade_started"
}) })
# Trigger the action # Trigger the action
IrisSystemThread('upgrade', self.upgrade_callback).start() IrisSystemThread('upgrade', ioloop, self.upgrade_callback).start()
response = { response = {
'message': "Upgrade started" 'message': "Upgrade started"
@ -532,9 +534,10 @@ class IrisCore(pykka.ThreadingActor):
## ##
def local_scan(self, *args, **kwargs): def local_scan(self, *args, **kwargs):
callback = kwargs.get('callback', False) callback = kwargs.get('callback', False)
ioloop = kwargs.get('ioloop', False)
# Trigger the action # Trigger the action
IrisSystemThread('local_scan', self.local_scan_callback).start() IrisSystemThread('local_scan', ioloop, self.local_scan_callback).start()
self.broadcast(data={ self.broadcast(data={
'method': "local_scan_started" 'method': "local_scan_started"
@ -1109,6 +1112,7 @@ class IrisCore(pykka.ThreadingActor):
## ##
def test(self, *args, **kwargs): def test(self, *args, **kwargs):
callback = kwargs.get('callback', False) callback = kwargs.get('callback', False)
ioloop = kwargs.get('ioloop', False)
self.broadcast(data={ self.broadcast(data={
'method': "test_started" 'method': "test_started"
@ -1123,14 +1127,19 @@ class IrisCore(pykka.ThreadingActor):
else: else:
return response 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: if error:
self.broadcast(data={ self.broadcast(data={
'method': "test_error", 'method': "test_error",
'params': error 'params': error
}) })
elif error:
self.broadcast(data={
'method': "test_update",
'params': update
})
else: else:
self.broadcast(data={ self.broadcast(data={
'method': "test_finished", 'method': "test_finished",

View File

@ -1,8 +1,6 @@
import pykka, logging, tornado
from mopidy.core import CoreListener from mopidy.core import CoreListener
from .core import IrisCore from .core import IrisCore
import pykka
import logging
from .mem import iris from .mem import iris
# import logger # import logger

View File

@ -13,6 +13,7 @@ class WebsocketHandler(tornado.websocket.WebSocketHandler):
def initialize(self, core, config): def initialize(self, core, config):
self.core = core self.core = core
self.config = config self.config = config
self.ioloop = tornado.ioloop.IOLoop.current()
def check_origin(self, origin): def check_origin(self, origin):
return True 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 # For async methods we need to await, but it must be ommited for syncronous methods
if asyncio.iscoroutinefunction(getattr(iris, message['method'])): 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: 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: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@ -133,6 +152,7 @@ class HttpHandler(tornado.web.RequestHandler):
def initialize(self, core, config): def initialize(self, core, config):
self.core = core self.core = core
self.config = config self.config = config
self.ioloop = tornado.ioloop.IOLoop.current()
# Options request # Options request
# This is a preflight request for CORS requests # 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 # For async methods we need to await, but it must be ommited for syncronous methods
if asyncio.iscoroutinefunction(getattr(iris, slug)): 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: 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: except Exception as e:
logger.error(str(e)) logger.error(str(e))
@ -174,9 +212,27 @@ class HttpHandler(tornado.web.RequestHandler):
if hasattr(iris, slug): if hasattr(iris, slug):
try: try:
if asyncio.iscoroutinefunction(getattr(iris, slug)): 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: 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: except tornado.web.HTTPError as e:
self.handle_result(id=id, error={'code': 32601, 'message': "Invalid JSON payload"}) self.handle_result(id=id, error={'code': 32601, 'message': "Invalid JSON payload"})

View File

@ -1,5 +1,5 @@
from threading import Thread from threading import Thread
import logging, os, pathlib, subprocess, json, tornado, sys, shlex import logging, os, pathlib, subprocess, json, sys
# import logger # import logger
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -21,11 +21,11 @@ class IrisSystemPermissionError(IrisSystemError):
class IrisSystemThread(Thread): class IrisSystemThread(Thread):
_USE_SUDO = True _USE_SUDO = True
def __init__(self, action, callback): def __init__(self, action, ioloop, callback):
Thread.__init__(self) Thread.__init__(self)
self.action = action self.action = action
self.callback = callback self.callback = callback
self.ioloop = tornado.ioloop.IOLoop.current() self.ioloop = ioloop
self.script_path = pathlib.Path(__file__).parent / "system.sh" self.script_path = pathlib.Path(__file__).parent / "system.sh"
def get_command(self, action=None, *, non_interactive=False): def get_command(self, action=None, *, non_interactive=False):