Rework whole TFW networking model

This commit is contained in:
Kristóf Tóth
2019-05-26 18:26:33 +02:00
parent 613919a5b6
commit 01d9003501
19 changed files with 155 additions and 279 deletions

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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 = {}

View 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

View File

@ -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)

View File

@ -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.

View File

@ -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)

View File

@ -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.

View File

@ -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):

View File

@ -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.

View File

@ -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