13
13
import threading
14
14
import time
15
15
from typing import Optional
16
+ from pathlib import Path
16
17
17
- import pyinotify
18
+ from watchdog .observers import Observer
19
+ from watchdog .events import FileSystemEventHandler
18
20
from dasbus .loop import EventLoop
19
21
from dasbus .signal import Signal
20
22
42
44
dbus_loop : Optional [EventLoop ] = None
43
45
44
46
45
- class NginxConfigReloader (pyinotify . ProcessEvent ):
46
- def my_init (
47
+ class NginxConfigReloader (FileSystemEventHandler ):
48
+ def __init__ (
47
49
self ,
48
50
logger = None ,
49
51
no_magento_config = False ,
@@ -79,36 +81,51 @@ def my_init(
79
81
self .applying = False
80
82
self ._on_config_reload = Signal ()
81
83
82
- def process_IN_DELETE (self , event ):
84
+ def on_deleted (self , event ):
83
85
"""Triggered by inotify on removal of file or removal of dir
84
86
85
87
If the dir itself is removed, inotify will stop watching and also
86
88
trigger IN_IGNORED.
87
89
"""
88
- if not event .dir : # Will also capture IN_DELETE_SELF
90
+ if not event .is_directory :
89
91
self .handle_event (event )
90
92
91
- def process_IN_MOVED (self , event ):
93
+ def on_moved (self , event ):
92
94
"""Triggered by inotify when a file is moved from or to the dir"""
93
95
self .handle_event (event )
94
96
95
- def process_IN_CREATE (self , event ):
97
+ def on_created (self , event ):
96
98
"""Triggered by inotify when a dir is created in the watch dir"""
97
- if event .dir :
99
+ if event .is_directory :
98
100
self .handle_event (event )
99
101
100
- def process_IN_CLOSE_WRITE (self , event ):
102
+ def on_modified (self , event ):
101
103
"""Triggered by inotify when a file is written in the dir"""
102
104
self .handle_event (event )
103
105
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
107
111
108
112
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 } " )
111
127
self .dirty = True
128
+ # Additional handling if necessary
112
129
113
130
def install_magento_config (self ):
114
131
# Check if configs are present
@@ -309,6 +326,20 @@ def reload(self, send_signal=True):
309
326
if send_signal :
310
327
self ._on_config_reload .emit ()
311
328
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 ()
312
343
313
344
class ListenTargetTerminated (BaseException ):
314
345
pass
@@ -357,20 +388,11 @@ def wait_loop(
357
388
"""
358
389
dir_to_watch = os .path .abspath (dir_to_watch )
359
390
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
-
368
391
nginx_config_changed_handler = NginxConfigReloader (
369
392
logger = logger ,
370
393
no_magento_config = no_magento_config ,
371
394
no_custom_config = no_custom_config ,
372
395
dir_to_watch = dir_to_watch ,
373
- notifier = notifier ,
374
396
use_systemd = use_systemd ,
375
397
)
376
398
@@ -383,35 +405,27 @@ def process_IN_DELETE(self, event):
383
405
dbus_thread = threading .Thread (target = dbus_event_loop )
384
406
dbus_thread .start ()
385
407
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 )
402
411
)
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
+
415
429
416
430
417
431
def as_unprivileged_user ():
0 commit comments