mirror of
https://github.com/avatao-content/baseimage-tutorial-framework
synced 2025-06-29 00:05:12 +00:00
Rework whole TFW networking model
This commit is contained in:
@ -14,3 +14,4 @@ from .pipe_io_event_handler import PipeIOEventHandlerBase, PipeIOEventHandler, P
|
||||
from .pipe_io_event_handler import TransformerPipeIOEventHandler, CommandEventHandler
|
||||
from .directory_snapshotting_event_handler import DirectorySnapshottingEventHandler
|
||||
from .commands_equal import CommandsEqual
|
||||
from .frontend_event_handler import FrontendEventHandler
|
||||
|
@ -5,7 +5,7 @@ from functools import wraps
|
||||
|
||||
from watchdog.events import FileSystemEventHandler as FileSystemWatchdogEventHandler
|
||||
|
||||
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector
|
||||
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector, Scope
|
||||
from tfw.decorators.rate_limiter import RateLimiter
|
||||
from tfw.mixins.observer_mixin import ObserverMixin
|
||||
|
||||
@ -65,10 +65,10 @@ class IdeReloadWatchdogEventHandler(FileSystemWatchdogEventHandler):
|
||||
self.ignore = self.ignore - 1
|
||||
return
|
||||
LOG.debug(event)
|
||||
self.uplink.send({
|
||||
self.uplink.send_message({
|
||||
'key': self.ide_key,
|
||||
'data': {'command': 'reload'}
|
||||
})
|
||||
}, Scope.WEBSOCKET)
|
||||
|
||||
|
||||
def with_monitor_paused(fun):
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from os.path import isdir, exists
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.mixins.monitor_manager_mixin import MonitorManagerMixin
|
||||
from tfw.components.directory_monitor import DirectoryMonitor
|
||||
from tfw.config.logs import logging
|
||||
@ -11,7 +11,7 @@ from tfw.config.logs import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DirectoryMonitoringEventHandler(EventHandlerBase, MonitorManagerMixin):
|
||||
class DirectoryMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
|
||||
def __init__(self, key, directory):
|
||||
super().__init__(key)
|
||||
self._directory = directory
|
||||
|
@ -8,7 +8,7 @@ from datetime import datetime
|
||||
|
||||
from dateutil import parser as dateparser
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.components.snapshot_provider import SnapshotProvider
|
||||
from tfw.config import TFWENV
|
||||
from tfw.config.logs import logging
|
||||
@ -16,7 +16,7 @@ from tfw.config.logs import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DirectorySnapshottingEventHandler(EventHandlerBase):
|
||||
class DirectorySnapshottingEventHandler(FrontendEventHandlerBase):
|
||||
def __init__(self, key, directories, exclude_unix_patterns=None):
|
||||
super().__init__(key)
|
||||
self.snapshot_providers = {}
|
||||
|
62
lib/tfw/components/frontend_event_handler.py
Normal file
62
lib/tfw/components/frontend_event_handler.py
Normal file
@ -0,0 +1,62 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from contextlib import suppress
|
||||
|
||||
from tfw.networking.message_sender import MessageSender
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
|
||||
|
||||
class FrontendEventHandler(FrontendEventHandlerBase):
|
||||
def __init__(self):
|
||||
frontend_keys = ('message', 'queueMessages', 'dashboard', 'console')
|
||||
self._frontend_message_storage = FrontendMessageStorage(frontend_keys)
|
||||
super().__init__((*frontend_keys, 'recover'))
|
||||
|
||||
def handle_event(self, message):
|
||||
self._frontend_message_storage.save_message(message)
|
||||
if message['key'] == 'recover':
|
||||
self.recover_frontend()
|
||||
return message
|
||||
|
||||
def recover_frontend(self):
|
||||
for message in self._frontend_message_storage.messages:
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
class MessageStorage(ABC):
|
||||
def __init__(self):
|
||||
self._messages = []
|
||||
|
||||
def save_message(self, message):
|
||||
with suppress(KeyError, AttributeError):
|
||||
if self._filter_message(message):
|
||||
self._messages.extend(self._transform_message(message))
|
||||
|
||||
@abstractmethod
|
||||
def _filter_message(self, message):
|
||||
raise NotImplementedError
|
||||
|
||||
def _transform_message(self, message): # pylint: disable=no-self-use
|
||||
yield message
|
||||
|
||||
def clear(self):
|
||||
self._messages.clear()
|
||||
|
||||
@property
|
||||
def messages(self):
|
||||
yield from self._messages
|
||||
|
||||
|
||||
class FrontendMessageStorage(MessageStorage):
|
||||
def __init__(self, keys):
|
||||
self._keys = keys
|
||||
super().__init__()
|
||||
|
||||
def _filter_message(self, message):
|
||||
key = message['key']
|
||||
return key in self._keys
|
||||
|
||||
def _transform_message(self, message):
|
||||
if message['key'] == 'queueMessages':
|
||||
yield from MessageSender.generate_messages_from_queue(message)
|
||||
else:
|
||||
yield message
|
@ -1,14 +1,15 @@
|
||||
# Copyright (C) 2018 Avatao.com Innovative Learning Kft.
|
||||
# All Rights Reserved. See LICENSE file for details.
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.crypto import KeyManager, sign_message, verify_message
|
||||
from tfw.config.logs import logging
|
||||
from tfw.networking.event_handlers.server_connector import Scope
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FSMManagingEventHandler(EventHandlerBase):
|
||||
class FSMManagingEventHandler(FrontendEventHandlerBase):
|
||||
"""
|
||||
EventHandler responsible for managing the state machine of
|
||||
the framework (TFW FSM).
|
||||
@ -42,7 +43,7 @@ class FSMManagingEventHandler(EventHandlerBase):
|
||||
fsm_update_message = self._fsm_updater.fsm_update
|
||||
sign_message(self.auth_key, message)
|
||||
sign_message(self.auth_key, fsm_update_message)
|
||||
self.server_connector.broadcast(fsm_update_message)
|
||||
self.server_connector.send_message(fsm_update_message, Scope.BROADCAST)
|
||||
return message
|
||||
except KeyError:
|
||||
LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
|
||||
|
@ -6,7 +6,7 @@ from glob import glob
|
||||
from fnmatch import fnmatchcase
|
||||
from typing import Iterable
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.mixins.monitor_manager_mixin import MonitorManagerMixin
|
||||
from tfw.components.directory_monitor import DirectoryMonitor
|
||||
from tfw.config.logs import logging
|
||||
@ -102,7 +102,7 @@ class FileManager: # pylint: disable=too-many-instance-attributes
|
||||
return relpath(self._filepath(filename), start=self._workdir)
|
||||
|
||||
|
||||
class IdeEventHandler(EventHandlerBase, MonitorManagerMixin):
|
||||
class IdeEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
|
||||
# pylint: disable=too-many-arguments,anomalous-backslash-in-string
|
||||
"""
|
||||
Event handler implementing the backend of our browser based IDE.
|
||||
|
@ -6,7 +6,7 @@ from os.path import dirname
|
||||
|
||||
from watchdog.events import PatternMatchingEventHandler as PatternMatchingWatchdogEventHandler
|
||||
|
||||
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector
|
||||
from tfw.networking.event_handlers.server_connector import ServerUplinkConnector, Scope
|
||||
from tfw.decorators.rate_limiter import RateLimiter
|
||||
from tfw.mixins.observer_mixin import ObserverMixin
|
||||
from tfw.mixins.supervisor_mixin import SupervisorLogMixin
|
||||
@ -47,11 +47,11 @@ class SendLogWatchdogEventHandler(PatternMatchingWatchdogEventHandler, Superviso
|
||||
|
||||
@RateLimiter(rate_per_second=5)
|
||||
def on_modified(self, event):
|
||||
self.uplink.send({
|
||||
self.uplink.send_message({
|
||||
'key': 'processlog',
|
||||
'data': {
|
||||
'command': 'new_log',
|
||||
'stdout': self.read_stdout(self.process_name, tail=self.log_tail),
|
||||
'stderr': self.read_stderr(self.process_name, tail=self.log_tail)
|
||||
}
|
||||
})
|
||||
}, Scope.BROADCAST)
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2018 Avatao.com Innovative Learning Kft.
|
||||
# All Rights Reserved. See LICENSE file for details.
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.mixins.monitor_manager_mixin import MonitorManagerMixin
|
||||
from tfw.components.log_monitor import LogMonitor
|
||||
from tfw.config.logs import logging
|
||||
@ -9,7 +9,7 @@ from tfw.config.logs import logging
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class LogMonitoringEventHandler(EventHandlerBase, MonitorManagerMixin):
|
||||
class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
|
||||
"""
|
||||
Monitors the output of a supervisor process (stdout, stderr) and
|
||||
sends the results to the frontend.
|
||||
|
@ -56,7 +56,7 @@ class PipeIOEventHandler(PipeIOEventHandlerBase):
|
||||
|
||||
def handle_pipe_event(self, message_bytes):
|
||||
json = loads(message_bytes)
|
||||
self.server_connector.send(json)
|
||||
self.send_message(json)
|
||||
|
||||
|
||||
class TransformerPipeIOEventHandler(PipeIOEventHandlerBase):
|
||||
@ -93,7 +93,7 @@ class TransformerPipeIOEventHandler(PipeIOEventHandlerBase):
|
||||
transformed_bytes = self._transform_in(message_bytes)
|
||||
if transformed_bytes:
|
||||
json_message = loads(transformed_bytes)
|
||||
self.server_connector.send(json_message)
|
||||
self.send_message(json_message)
|
||||
|
||||
|
||||
class CommandEventHandler(PipeIOEventHandler):
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
from xmlrpc.client import Fault as SupervisorFault
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.mixins.supervisor_mixin import SupervisorMixin, SupervisorLogMixin
|
||||
from tfw.components.directory_monitor import with_monitor_paused
|
||||
from tfw.config.logs import logging
|
||||
@ -23,7 +23,7 @@ class ProcessManager(SupervisorMixin, SupervisorLogMixin):
|
||||
return self.commands[command](process_name)
|
||||
|
||||
|
||||
class ProcessManagingEventHandler(EventHandlerBase):
|
||||
class ProcessManagingEventHandler(FrontendEventHandlerBase):
|
||||
"""
|
||||
Event handler that can manage processes managed by supervisor.
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# Copyright (C) 2018 Avatao.com Innovative Learning Kft.
|
||||
# All Rights Reserved. See LICENSE file for details.
|
||||
|
||||
from tfw.event_handler_base import EventHandlerBase
|
||||
from tfw.event_handler_base import FrontendEventHandlerBase
|
||||
from tfw.components.terminado_mini_server import TerminadoMiniServer
|
||||
from tfw.config import TFWENV
|
||||
from tfw.config.logs import logging
|
||||
@ -10,7 +10,7 @@ from tao.config import TAOENV
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TerminalEventHandler(EventHandlerBase):
|
||||
class TerminalEventHandler(FrontendEventHandlerBase):
|
||||
"""
|
||||
Event handler responsible for managing terminal sessions for frontend xterm
|
||||
sessions to connect to. You need to instanciate this in order for frontend
|
||||
|
Reference in New Issue
Block a user