[core] Re-organize
This commit is contained in:
parent
272532b389
commit
36c2873532
3 changed files with 52 additions and 52 deletions
ovtk_audiencekit
|
@ -22,8 +22,7 @@ from ovtk_audiencekit.core import WebsocketServerProcess
|
|||
from ovtk_audiencekit.core.Config import kdl_parse_config, kdl_reserved
|
||||
from ovtk_audiencekit.events import Event, Delete
|
||||
from ovtk_audiencekit.chats.ChatProcess import ShutdownRequest
|
||||
from ovtk_audiencekit.plugins import builtins
|
||||
from ovtk_audiencekit.plugins.PluginBase import PluginError
|
||||
from ovtk_audiencekit.plugins import builtins, PluginError
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
@ -118,6 +117,27 @@ class MainProcess:
|
|||
event = pipe.recv()
|
||||
self.event_queue.put_nowait(event)
|
||||
|
||||
def _setup_webserver(self):
|
||||
self.webserver = Quart(__name__, static_folder=None, template_folder=None)
|
||||
listen = ':'.join(self.web_conf)
|
||||
self.webserver.config['SERVER_NAME'] = listen
|
||||
|
||||
async def serve_coro():
|
||||
config = hypercorn.config.Config()
|
||||
config.bind = listen
|
||||
config.use_reloader = False
|
||||
config.logger_class = HypercornLoggingShim
|
||||
try:
|
||||
await hypercorn.asyncio.serve(self.webserver, config, shutdown_trigger=self.shutdown_ev.wait)
|
||||
except Exception as e:
|
||||
logger.critical(f'Failure in web process - {e}')
|
||||
logger.debug(''.join(format_exception(None, e, e.__traceback__)))
|
||||
raise e
|
||||
# MAGIC: As root tasks are supposed to be infinte loops, raise an exception if hypercorn shut down
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
return serve_coro()
|
||||
|
||||
async def handle_events(self):
|
||||
while True:
|
||||
event = await self.event_queue.get()
|
||||
|
@ -152,7 +172,20 @@ class MainProcess:
|
|||
else:
|
||||
logger.error(f'Unknown data in event loop - {event}')
|
||||
|
||||
def user_setup(self):
|
||||
async def tick_plugins(self):
|
||||
while True:
|
||||
await asyncio.sleep(0.5)
|
||||
for plugin_name, plugin in list(self.plugins.items()):
|
||||
try:
|
||||
res = plugin.tick(0.5) # Not necesarily honest!
|
||||
if asyncio.iscoroutinefunction(plugin.tick):
|
||||
await res
|
||||
except Exception as e:
|
||||
logger.critical(f'Failure during background processing for {plugin_name} ({e}) - disabling...')
|
||||
logger.debug(''.join(format_exception(None, e, e.__traceback__)))
|
||||
self._unload_plugin(plugin_name)
|
||||
|
||||
async def user_setup(self):
|
||||
config = kdl.Document(list(parse_kdl_deep(self.config_path)))
|
||||
stdin_lock = Lock()
|
||||
# Load secrets
|
||||
|
@ -242,41 +275,6 @@ class MainProcess:
|
|||
del self.plugins[plugin_name]
|
||||
sys.path = self._initial_syspath
|
||||
|
||||
async def tick_plugins(self):
|
||||
while True:
|
||||
await asyncio.sleep(0.5)
|
||||
for plugin_name, plugin in list(self.plugins.items()):
|
||||
try:
|
||||
res = plugin.tick(0.5) # Not necesarily honest!
|
||||
if asyncio.iscoroutinefunction(plugin.tick):
|
||||
await res
|
||||
except Exception as e:
|
||||
logger.critical(f'Failure during background processing for {plugin_name} ({e}) - disabling...')
|
||||
logger.debug(''.join(format_exception(None, e, e.__traceback__)))
|
||||
self._unload_plugin(plugin_name)
|
||||
|
||||
|
||||
def _setup_webserver(self):
|
||||
self.webserver = Quart(__name__, static_folder=None, template_folder=None)
|
||||
listen = ':'.join(self.web_conf)
|
||||
self.webserver.config['SERVER_NAME'] = listen
|
||||
|
||||
async def serve_coro():
|
||||
config = hypercorn.config.Config()
|
||||
config.bind = listen
|
||||
config.use_reloader = False
|
||||
config.logger_class = HypercornLoggingShim
|
||||
try:
|
||||
await hypercorn.asyncio.serve(self.webserver, config, shutdown_trigger=self.shutdown_ev.wait)
|
||||
except Exception as e:
|
||||
logger.critical(f'Failure in web process - {e}')
|
||||
logger.debug(''.join(format_exception(None, e, e.__traceback__)))
|
||||
raise e
|
||||
# MAGIC: As root tasks are supposed to be infinte loops, raise an exception if hypercorn shut down
|
||||
raise asyncio.CancelledError()
|
||||
|
||||
return serve_coro()
|
||||
|
||||
async def run(self):
|
||||
self.shutdown_ev = asyncio.Event()
|
||||
self.reload_ev = asyncio.Event()
|
||||
|
@ -314,7 +312,7 @@ class MainProcess:
|
|||
# User (plugin / chat) mode (reloading allowed)
|
||||
while True:
|
||||
async with self.webserver.app_context():
|
||||
self.user_setup()
|
||||
await self.user_setup()
|
||||
# Start plumbing tasks
|
||||
user_tasks.add(loop.create_task(self.tick_plugins()))
|
||||
user_tasks.add(loop.create_task(self.handle_events()))
|
||||
|
@ -341,7 +339,7 @@ class MainProcess:
|
|||
except KeyboardInterrupt:
|
||||
pass
|
||||
except kdl.errors.ParseError as e:
|
||||
if (e.file):
|
||||
if e.file:
|
||||
logger.critical(f'Invalid configuration in {e.file} at {e.line}:{e.col} - {e.msg}')
|
||||
else:
|
||||
logger.critical(f'Invalid configuration - {e.msg}')
|
||||
|
|
|
@ -31,6 +31,14 @@ class GetitemFormatter(Formatter):
|
|||
return (field, keys[0])
|
||||
|
||||
|
||||
class OvtkBlueprint(quart.Blueprint):
|
||||
def url_for(self, endpoint, *args, **kwargs):
|
||||
"""url_for method that understands blueprint-relative names under non-request contexts"""
|
||||
if endpoint.startswith('.'):
|
||||
endpoint = self.name + endpoint
|
||||
return quart.url_for(endpoint, *args, **kwargs)
|
||||
|
||||
|
||||
class PluginBase(ABC):
|
||||
plugins = {}
|
||||
|
||||
|
@ -46,17 +54,11 @@ class PluginBase(ABC):
|
|||
|
||||
# HACK: This is kinda gross, and probably wont be true for frozen modules
|
||||
plugin_dir = os.path.dirname(sys.modules[self.__class__.__module__].__file__)
|
||||
self.blueprint = quart.Blueprint(self._name, __name__,
|
||||
url_prefix=f'/{self._name}',
|
||||
static_url_path='static',
|
||||
static_folder=os.path.join(plugin_dir, 'static'),
|
||||
template_folder=os.path.join(plugin_dir, 'templates'))
|
||||
def url_for(endpoint, *args, **kwargs):
|
||||
"""Monkey-patched url_for method that understands blueprint-relative names, even under non-request contexts"""
|
||||
if endpoint.startswith('.'):
|
||||
endpoint = self._name + endpoint
|
||||
return quart.url_for(endpoint, *args, **kwargs)
|
||||
self.blueprint.url_for = url_for
|
||||
self.blueprint = OvtkBlueprint(self._name, __name__,
|
||||
url_prefix=f'/{self._name}',
|
||||
static_url_path='static',
|
||||
static_folder=os.path.join(plugin_dir, 'static'),
|
||||
template_folder=os.path.join(plugin_dir, 'templates'))
|
||||
|
||||
if _children:
|
||||
raise ValueError('Module does not accept children')
|
|
@ -1,3 +1,3 @@
|
|||
from .PluginBase import PluginBase, PluginError
|
||||
from ovtk_audiencekit.core.PluginBase import PluginBase, PluginError
|
||||
|
||||
__all__ = ['PluginBase', 'PluginError']
|
||||
|
|
Loading…
Add table
Reference in a new issue