Skip to content

Instantly share code, notes, and snippets.

@smola
Last active June 30, 2023 06:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smola/d40614a9b546a650d87bc3588efc1014 to your computer and use it in GitHub Desktop.
Save smola/d40614a9b546a650d87bc3588efc1014 to your computer and use it in GitHub Desktop.
Issue with watchdog PollingObserver missing events when removing files
# 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