1313import threading
1414import time
1515from typing import Optional
16+ from pathlib import Path
1617
17- import pyinotify
18+ from watchdog .observers import Observer
19+ from watchdog .events import FileSystemEventHandler
1820from dasbus .loop import EventLoop
1921from dasbus .signal import Signal
2022
4244dbus_loop : Optional [EventLoop ] = None
4345
4446
45- class NginxConfigReloader (pyinotify . ProcessEvent ):
46- def my_init (
47+ class NginxConfigReloader (FileSystemEventHandler ):
48+ def __init__ (
4749 self ,
4850 logger = None ,
4951 no_magento_config = False ,
@@ -79,36 +81,51 @@ def my_init(
7981 self .applying = False
8082 self ._on_config_reload = Signal ()
8183
82- def process_IN_DELETE (self , event ):
84+ def on_deleted (self , event ):
8385 """Triggered by inotify on removal of file or removal of dir
8486
8587 If the dir itself is removed, inotify will stop watching and also
8688 trigger IN_IGNORED.
8789 """
88- if not event .dir : # Will also capture IN_DELETE_SELF
90+ if not event .is_directory :
8991 self .handle_event (event )
9092
91- def process_IN_MOVED (self , event ):
93+ def on_moved (self , event ):
9294 """Triggered by inotify when a file is moved from or to the dir"""
9395 self .handle_event (event )
9496
95- def process_IN_CREATE (self , event ):
97+ def on_created (self , event ):
9698 """Triggered by inotify when a dir is created in the watch dir"""
97- if event .dir :
99+ if event .is_directory :
98100 self .handle_event (event )
99101
100- def process_IN_CLOSE_WRITE (self , event ):
102+ def on_modified (self , event ):
101103 """Triggered by inotify when a file is written in the dir"""
102104 self .handle_event (event )
103105
104- def process_IN_MOVE_SELF (self , event ):
105- """Triggered by inotify when watched dir is moved"""
106- raise ListenTargetTerminated
106+ def on_any_event (self , event ):
107+ """Triggered by inotify when watched dir is moved or deleted"""
108+ if event .is_directory and event .event_type in ['moved' , 'deleted' ]:
109+ self .logger .warning (f"Directory { event .src_path } has been { event .event_type } ." )
110+ raise ListenTargetTerminated
107111
108112 def handle_event (self , event ):
109- if not any (fnmatch .fnmatch (event .name , pat ) for pat in WATCH_IGNORE_FILES ):
110- self .logger .info ("{} detected on {}." .format (event .maskname , event .name ))
113+ file_path = Path (event .src_path )
114+ if (
115+ file_path .name .endswith (".swx" )
116+ or file_path .name .endswith (".swp" )
117+ or file_path .name .endswith ("~" )
118+ ):
119+ return
120+
121+ if (event .is_directory ):
122+ return
123+
124+ basename = os .path .basename (event .src_path )
125+ if not any (fnmatch .fnmatch (basename , pat ) for pat in WATCH_IGNORE_FILES ):
126+ self .logger .debug (f"{ event .event_type .upper ()} detected on { event .src_path } " )
111127 self .dirty = True
128+ # Additional handling if necessary
112129
113130 def install_magento_config (self ):
114131 # Check if configs are present
@@ -309,6 +326,20 @@ def reload(self, send_signal=True):
309326 if send_signal :
310327 self ._on_config_reload .emit ()
311328
329+ def start_observer (self ):
330+ self .observer = Observer ()
331+ self .observer .schedule (
332+ self ,
333+ self .dir_to_watch ,
334+ recursive = True ,
335+ follow_symlink = True
336+ )
337+ self .observer .start ()
338+
339+ def stop_observer (self ):
340+ self .observer .stop ()
341+ self .observer .join ()
342+ sys .exit ()
312343
313344class ListenTargetTerminated (BaseException ):
314345 pass
@@ -357,20 +388,11 @@ def wait_loop(
357388 """
358389 dir_to_watch = os .path .abspath (dir_to_watch )
359390
360- wm = pyinotify .WatchManager ()
361- notifier = pyinotify .Notifier (wm )
362-
363- class SymlinkChangedHandler (pyinotify .ProcessEvent ):
364- def process_IN_DELETE (self , event ):
365- if event .pathname == dir_to_watch :
366- raise ListenTargetTerminated ("watched directory was deleted" )
367-
368391 nginx_config_changed_handler = NginxConfigReloader (
369392 logger = logger ,
370393 no_magento_config = no_magento_config ,
371394 no_custom_config = no_custom_config ,
372395 dir_to_watch = dir_to_watch ,
373- notifier = notifier ,
374396 use_systemd = use_systemd ,
375397 )
376398
@@ -383,35 +405,27 @@ def process_IN_DELETE(self, event):
383405 dbus_thread = threading .Thread (target = dbus_event_loop )
384406 dbus_thread .start ()
385407
386- while True :
387- while not os .path .exists (dir_to_watch ):
388- logger .warning (
389- "Configuration dir {} not found, waiting..." .format (dir_to_watch )
390- )
391- time .sleep (5 )
392-
393- wm .add_watch (
394- dir_to_watch ,
395- pyinotify .ALL_EVENTS ,
396- nginx_config_changed_handler ,
397- rec = recursive_watch ,
398- auto_add = True ,
399- )
400- wm .watch_transient_file (
401- dir_to_watch , pyinotify .ALL_EVENTS , SymlinkChangedHandler
408+ while not os .path .exists (dir_to_watch ):
409+ logger .warning (
410+ "Configuration dir {} not found, waiting..." .format (dir_to_watch )
402411 )
403-
404- # Install initial configuration
405- nginx_config_changed_handler .reload (send_signal = False )
406-
407- try :
408- logger .info ("Listening for changes to {}" .format (dir_to_watch ))
409- notifier .coalesce_events ()
410- notifier .loop (callback = lambda _ : after_loop (nginx_config_changed_handler ))
411- except pyinotify .NotifierError as err :
412- logger .critical (err )
413- except ListenTargetTerminated :
414- logger .warning ("Configuration dir lost, waiting for it to reappear" )
412+ time .sleep (5 )
413+
414+
415+ try :
416+ logger .info (f"Listening for changes to { dir_to_watch } " )
417+ nginx_config_changed_handler .start_observer ()
418+ while True :
419+ time .sleep (1 )
420+ after_loop (nginx_config_changed_handler )
421+ except ListenTargetTerminated :
422+ logger .warning ("Configuration dir lost, waiting for it to reappear" )
423+ nginx_config_changed_handler .stop_observer ()
424+ time .sleep (5 )
425+ except KeyboardInterrupt :
426+ logger .info ("Shutting down observer." )
427+ nginx_config_changed_handler .stop_observer ()
428+
415429
416430
417431def as_unprivileged_user ():
0 commit comments