gmethvin / directory-watcher

A cross-platform Java recursive directory watcher, with a JNA macOS watcher and Scala better-files integration
Apache License 2.0
264 stars 34 forks source link

Does it work with mounted volumes with Docker? #86

Open chrisvoo opened 1 year ago

chrisvoo commented 1 year ago

Hi! This is just a question to investigate if you had the chance to test it within a Docker context. Currently, I have a Java 8 microservice with a watching thread (using java.nio.file.WatcherService) that listens to changes to a bind-mounted directory. Here is the relevant part inside the docker-compose config:

services:
  filemanager:
    container_name: filemanager
    restart: always
    build:
      context: filemanager
      dockerfile: Dockerfile
    image: filemanager:latest
    ports:
      - ${FILE_MANAGER_PORT}:${FILE_MANAGER_PORT}
    environment:
      - FILE_MANAGER_PORT=${FILE_MANAGER_PORT}
      - MUSIC_DIRECTORY=${MUSIC_CONTAINER_DIRECTORY}
      - MYSQL_HOST=${MYSQL_CONTAINER_NAME}
      - MYSQL_PORT=${MYSQL_LOCAL_PORT}
      - MYSQL_DATABASE=${MYSQL_DATABASE}
      - MYSQL_USER=${MYSQL_USER}
      - MYSQL_PASSWORD=${MYSQL_PASSWORD}
      - ENV=DEVELOPMENT
    volumes:
      - ${MUSIC_LOCAL_DIRECTORY}:${MUSIC_CONTAINER_DIRECTORY}
    depends_on:
      - mysql

If I run it without Docker or modify files directly inside Docker, the events are correctly dispatched and captured. If instead, I modify files on Ubuntu (MUSIC_LOCAL_DIRECTORY), just the files are modified inside the container but no events get captured. I'm trying to understand if I need to do something different or if this feature cannot be used in this context (as said in this post for example). Thanks!

gmethvin commented 1 year ago

On Linux, directory-watcher defaults to using the default JDK WatchService, which uses inotify. As mentioned in the post you linked, inotify doesn't see certain events on mapped file systems.

gmethvin commented 1 year ago

One possible solution should be to just switch to the PollingWatchService implementation but apparently it's not simple to do that: https://stackoverflow.com/questions/28732693/is-there-a-way-for-force-polling-using-watchservice

I haven't looked into the specifics required to get it working, but a forced polling implementation would be a useful feature to add to this library. Of course for some use cases polling won't be fast enough, but it's better than nothing.

chrisvoo commented 1 year ago

Thanks @gmethvin , I noticed an upgrade after having upgraded to Docker Desktop 4.15.0, in which they solved this issue, however, I'm still not able to catch DELETE events, for which I opened a new issue here.
My use case is monitoring recursively a directory with more or less 25K files in it. Whenever I create or delete a file, I want to sync this operation with MySQL, where all the files are saved in a table (so add/remove a row from a table). Given the number of files, I'm dubious that polling can be effective, but I haven't tried.

gmethvin commented 1 year ago

Okay, that's an improvement at least. It sounds like you're looking at the inotify logs so this isn't the issue, but make sure you're on 0.17.1 since I recently fixed an issue with reporting deletions.

Also for your use case you might consider using the ChangeSetListener, which tries to group changes together when there are a series of many operations at once.