Replace mixins with inotify based observers

This commit is contained in:
R. Richard
2019-06-24 14:29:31 +02:00
committed by Kristóf Tóth
parent 597523b3b9
commit 494761d2a7
7 changed files with 71 additions and 222 deletions

View File

@ -2,20 +2,29 @@
# All Rights Reserved. See LICENSE file for details.
import logging
from os.path import isfile, join, relpath, exists, isdir, realpath
from glob import glob
from fnmatch import fnmatchcase
from typing import Iterable
from tfw.event_handlers import FrontendEventHandlerBase
from tfw.mixins.monitor_manager_mixin import MonitorManagerMixin
from tfw.networking import Scope
from tfw.event_handlers import FrontendEventHandlerBase, TFWServerUplinkConnector
from tfw.components import FileManager
from tfw.components.directory_monitor import DirectoryMonitor
from tfw.components.inotify import InotifyObserver
LOG = logging.getLogger(__name__)
class IdeEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
class IdeInotifyObserver(InotifyObserver):
def __init__(self, paths):
self.uplink = TFWServerUplinkConnector()
super().__init__(paths)
def on_modified(self, event):
LOG.debug(event)
self.uplink.send_message({
'key': 'ide',
'data': {'command': 'reload'}
}, Scope.WEBSOCKET)
class IdeEventHandler(FrontendEventHandlerBase):
# pylint: disable=too-many-arguments,anomalous-backslash-in-string
"""
Event handler implementing the backend of our browser based IDE.
@ -51,12 +60,8 @@ class IdeEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
f'No file(s) in IdeEventHandler working_directory "{directory}"!'
)
MonitorManagerMixin.__init__(
self,
DirectoryMonitor,
self.key,
self.filemanager.allowed_directories
)
self.monitor = IdeInotifyObserver(self.filemanager.allowed_directories)
self.monitor.start()
self.commands = {
'read': self.read,
@ -91,7 +96,6 @@ class IdeEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
(new file content)
"""
self.monitor.ignore = self.monitor.ignore + 1
try:
self.filemanager.file_contents = data['content']
except Exception: # pylint: disable=broad-except
@ -123,7 +127,6 @@ class IdeEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
"""
try:
self.filemanager.workdir = data['directory']
self.reload_monitor()
try:
self.filemanager.filename = self.filemanager.files[0]
self.read(data)

View File

@ -3,14 +3,57 @@
import logging
from tfw.event_handlers import FrontendEventHandlerBase
from tfw.mixins.monitor_manager_mixin import MonitorManagerMixin
from tfw.components.log_monitor import LogMonitor
from os.path import dirname
from tfw.networking import Scope
from tfw.event_handlers import FrontendEventHandlerBase, TFWServerUplinkConnector
from tfw.components.inotify import InotifyObserver
from tfw.mixins.supervisor_mixin import SupervisorLogMixin
LOG = logging.getLogger(__name__)
class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
class LogInotifyObserver(InotifyObserver, SupervisorLogMixin):
def __init__(self, process_name, log_tail=0):
self.prevent_log_recursion()
self.uplink = TFWServerUplinkConnector()
self.process_name = process_name
self.log_tail = log_tail
self.procinfo = self.supervisor.getProcessInfo(self.process_name)
super().__init__(
[dirname(self.procinfo['stdout_logfile']), dirname(self.procinfo['stderr_logfile'])],
[self.procinfo['stdout_logfile'], self.procinfo['stderr_logfile']]
)
def reset(self, process_name, log_tail):
self.process_name = process_name
self.log_tail = log_tail
self.procinfo = self.supervisor.getProcessInfo(self.process_name)
self.paths = [
dirname(self.procinfo['stdout_logfile']),
dirname(self.procinfo['stderr_logfile'])
]
self.patterns = [
self.procinfo['stdout_logfile'],
self.procinfo['stderr_logfile']
]
def on_modified(self, event):
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)
@staticmethod
def prevent_log_recursion():
# This is done to prevent inotify event logs triggering themselves (infinite log recursion)
logging.getLogger('watchdog.observers.inotify_buffer').propagate = False
class LogMonitoringEventHandler(FrontendEventHandlerBase):
"""
Monitors the output of a supervisor process (stdout, stderr) and
sends the results to the frontend.
@ -24,12 +67,8 @@ class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
super().__init__(key)
self.process_name = process_name
self.log_tail = log_tail
MonitorManagerMixin.__init__(
self,
LogMonitor,
self.process_name,
self.log_tail
)
self.monitor = LogInotifyObserver(process_name, log_tail)
self.monitor.start()
self.command_handlers = {
'process_name': self.handle_process_name,
@ -40,7 +79,6 @@ class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
try:
data = message['data']
self.command_handlers[data['command']](data)
self.reload_monitor()
except KeyError:
LOG.error('IGNORING MESSAGE: Invalid message received: %s', message)
@ -51,7 +89,7 @@ class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
:param data: TFW message data containing 'value'
(name of the process to monitor)
"""
self.set_monitor_args(data['value'], self.log_tail)
self.monitor.reset(data['value'], self.log_tail)
def handle_log_tail(self, data):
"""
@ -62,7 +100,7 @@ class LogMonitoringEventHandler(FrontendEventHandlerBase, MonitorManagerMixin):
:param data: TFW message data containing 'value'
(new tail length)
"""
self.set_monitor_args(self.process_name, data['value'])
self.monitor.reset(self.process_name, data['value'])
def cleanup(self):
self.monitor.stop()

View File

@ -6,7 +6,6 @@ from xmlrpc.client import Fault as SupervisorFault
from tfw.event_handlers import FrontendEventHandlerBase
from tfw.mixins.supervisor_mixin import SupervisorMixin, SupervisorLogMixin
from tfw.components.directory_monitor import with_monitor_paused
LOG = logging.getLogger(__name__)
@ -36,13 +35,11 @@ class ProcessManagingEventHandler(FrontendEventHandlerBase):
Commands available: start, stop, restart, readlog
(the names are as self-documenting as it gets)
"""
def __init__(self, key, dirmonitor=None, log_tail=0):
def __init__(self, key, log_tail=0):
super().__init__(key)
self.monitor = dirmonitor
self.processmanager = ProcessManager()
self.log_tail = log_tail
@with_monitor_paused
def handle_event(self, message):
try:
data = message['data']