Last active
June 30, 2023 06:15
-
-
Save smola/d40614a9b546a650d87bc3588efc1014 to your computer and use it in GitHub Desktop.
Issue with watchdog PollingObserver missing events when removing files
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Reproduction for https://github.com/gorakhargosh/watchdog/issues/992 | |
from tempfile import TemporaryDirectory | |
import time | |
import os | |
import os.path | |
from multiprocessing import Process, Queue | |
from pathlib import Path | |
from watchdog.observers.polling import PollingObserver | |
from watchdog.events import FileSystemEventHandler | |
TOTAL_FILES = 100 | |
def generate_events(tmp_dir, q): | |
for i in range(1, TOTAL_FILES + 1): | |
time.sleep(0.1) | |
p = Path(os.path.join(tmp_dir, f"{i}")) | |
p.touch() | |
inode = os.stat(p).st_ino | |
q.put(("created", i, inode)) | |
time.sleep(2) | |
q.put(("DONE", None, None)) | |
class Event(FileSystemEventHandler): | |
def __init__(self, queue) -> None: | |
self._processed = 0 | |
self._queue = queue | |
def dispatch(self, event): | |
print(f"Event: {event}") | |
if event.is_directory: | |
return | |
if event.event_type not in ("modified", "created"): | |
return | |
if event.src_path.endswith(".processed"): | |
return | |
dst_path = event.src_path + ".processed" | |
Path(dst_path).touch() | |
inode = os.stat(dst_path).st_ino | |
i = int(event.src_path.split("/")[-1]) | |
if os.path.exists(event.src_path): | |
os.remove(event.src_path) | |
self._processed += 1 | |
q.put(("processed", i, inode)) | |
else: | |
q.put(("processed-not-found", i, inode)) | |
with TemporaryDirectory() as tmp_dir: | |
print(f"TMP_DIR: {tmp_dir}") | |
q = Queue() | |
observer = PollingObserver(timeout=1) | |
observer.schedule(Event(queue=q), path=tmp_dir) | |
observer.start() | |
p = Process(target=generate_events, args=(tmp_dir, q)) | |
p.start() | |
_seen = {"processed": list(), "processed-not-found": list(), "created": list()} | |
while True: | |
ev, i, inode = q.get() | |
if ev == "DONE": | |
break | |
print((ev, i, inode)) | |
_seen[ev].append(i) | |
print(f"Created {len(_seen['created'])} files: {_seen['created']}") | |
print(f"Processed {len(_seen['processed'])} files: {_seen['processed']}") | |
print(f"Not found {len(_seen['processed-not-found'])} files: {_seen['processed-not-found']}") | |
missing = set(_seen["created"]) - set(_seen["processed"]) | |
print(f"Missing processing: {missing}") | |
not_seen_at_all = set(_seen["created"]) - set(_seen["processed"]) - set(_seen["processed-not-found"]) | |
print(f"Not seen at all: {not_seen_at_all}") | |
p.join() | |
print("File creator process finished") | |
print("Stopping observer") | |
observer.stop() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment