import os import time from watchdog.observers import Observer from watchdog.events import PatternMatchingEventHandler class FileSystemWatcherService: """ Servizio di backend che monitora il file system per cambiamenti e pubblica eventi sull'Event Bus del Kernel. """ def __init__(self, core_api, config): self.core = core_api self.config_watches = config.get('watches', []) self.observer = Observer() def start(self): self.log("Avvio servizio...") if not self.config_watches: self.log("Nessuna cartella da monitorare definita nella configurazione.", 'warning') return for watch_config in self.config_watches: path = watch_config.get('path') if not os.path.isabs(path): path = os.path.join(self.core.base_dir, path) # --- NUOVA RIGA: Normalizza il percorso --- # Questo risolve i ".." e i "." e restituisce un percorso pulito. path = os.path.normpath(path) if not os.path.isdir(path): self.log(f"La cartella da monitorare non esiste: {path}", 'error') continue patterns = watch_config.get('patterns', ['*']) recursive = watch_config.get('recursive', False) event_to_publish = watch_config.get('event_to_publish') # Crea un gestore di eventi specifico per questa configurazione event_handler = self.create_event_handler(patterns, event_to_publish) # Schedula il monitoraggio self.observer.schedule(event_handler, path, recursive=recursive) self.log(f"Monitoraggio attivato per la cartella: {path}") self.observer.start() self.log("Servizio avviato e operativo.") def stop(self): self.log("Arresto servizio...") if self.observer.is_alive(): self.observer.stop() self.observer.join() # Attende la terminazione del thread self.log("Servizio fermato.") def log(self, message, level='info'): self.core.log(f"[FSWATCHER] {message}", level) def create_event_handler(self, patterns, event_to_publish): """Factory per creare gestori di eventi personalizzati.""" # Usiamo una classe interna per avere accesso facile al core class Handler(PatternMatchingEventHandler): def __init__(self, core_api, event_name, **kwargs): super().__init__(**kwargs) self.core = core_api self.event_name = event_name def on_created(self, event): self.process(event) def on_modified(self, event): self.process(event) def process(self, event): """Metodo generico per processare un evento del file system.""" if event.is_directory: return # Ignoriamo gli eventi relativi alle cartelle # Pubblichiamo l'evento sull'Event Bus del Core self.core.publish_event(self.event_name, { "event_type": event.event_type, "path": event.src_path, "is_directory": event.is_directory }) return Handler( core_api=self.core, event_name=event_to_publish, patterns=patterns, ignore_directories=True, case_sensitive=False )