Erlang: создать FileWatcher - PullRequest
       3

Erlang: создать FileWatcher

5 голосов
/ 16 апреля 2011

Я должен реализовать функцию наблюдателя файлов в Erlang: должен быть процесс, который выводит список файлов, если конкретный каталог, и что-то делает, когда файлы появляются.

Я смотрю на OTP.Итак, на данный момент у меня есть следующие идеи: 1. Создать Supervisor, который будет управлять gen_servers (один сервер на папку) 2. Создать WatchServer - gen_server для каждой папки, которую я хочу отслеживать.3. Создайте ProcessFileServer - общий сервер, который должен что-то делать с файлами). Предположим, что копия в другую папку =

Итак. Первая проблема: WatchServer не должен ждать запроса, он должен генерировать его в заданные интервалы.

На данный момент я создал таймер в функции init / 1 и обработал событие on_timer в функции handle_info.

Теперь вопросы: 1. Есть ли лучшие идеи?2. Как мне сообщить ProcessFileServer, что файл найден?Мне кажется, что было бы гораздо удобнее создавать WatchServers и ProcessServers независимо, но в этом случае я не знаю, кому отправлять сообщения?

Может быть, есть несколько похожих проектов или библиотек?

Ответы [ 3 ]

4 голосов
/ 16 апреля 2011

если вы используете Linux, вы можете использовать inotify.Это служба ядра, которая позволяет вам подписаться на события файловой системы.Не опрашивайте файловую систему, позвольте файловой системе позвонить вам.

вы можете попробовать https://github.com/massemanet/inotify для наблюдения за вашим каталогом.

Ульф

2 голосов
/ 18 апреля 2011

Я написал такую ​​библиотеку, основанную на опросе. (Было бы неплохо расширить его для использования inotify на платформах, где это поддерживается.) Первоначально он предназначался для использования в EUnit, но вместо этого я превратился в отдельный проект. Вы можете найти его здесь:

https://github.com/richcarl/file_monitor

2 голосов
/ 16 апреля 2011

В Erlang очень дешево создавать процессы (порядки величин по сравнению с другими системами).

Поэтому я рекомендую создавать новый ProcessFileServer каждый раз, когда появляется новый файл для обработки. Когда это будет сделано, просто завершите процесс с причиной выхода normal.

Я бы предложил следующую структуру:

                              top_supervisor
                                      |
              +-----------------------+-------------------------+
              |                                                 |
       directory_supervisor                             processing_supervisor
               |                                         simple_one_for_one
    +----------+-----...-----+                                   |
    |          |             |                       starts children transient
    |          |             |                                   |
dir_watcher_1 dir_watcher_2 dir_watcher_n   +-------------+------+---...----+
                                            |             |                 |
                                        proc_file_1   proc_file_2       proc_file_n

Когда dir_watcher замечает, появился новый файл. Он вызывает функцию processing_supervisor s supervisor:start_child\2 с дополнительным параметром файла pathe, например,

processing_supervisor должен начинать своих детей с transient политики перезапуска.

Таким образом, если один из серверов proc_file дает сбой, он будет перезапущен, но когда он завершит работу с причиной выхода normal, он не будет перезапущен. Таким образом, вы просто выходите из normal, когда закончите, и вылетаете, когда что-то еще происходит.

Если вы не переусердствуете, циклический опрос для файлов в порядке. Если система становится загруженной из-за этого опроса, вы можете исследовать в системах уведомлений ядра (например, FreeBSD KQUEUE или сервисы более высокого уровня, основанные на этом на MacOSX), чтобы отправить вам сообщение, когда файл появляется в каталоге. Эти сервисы, однако, имеют сложность, потому что им необходимо поднять руки, если происходит слишком много событий (в противном случае они не улучшат производительность, а наоборот). Так что в любом случае вам понадобится надежное решение для опроса.

Так что не делайте преждевременную оптимизацию и начинайте с опроса, добавляя улучшения (которые будут изолированы на dir_watcher серверах), когда это будет необходимо.


Относительно комментария, какое поведение использовать как dir_watcher процесс, так как он не использует большую часть gen_servers функциональности:

  • Нет проблем с использованием только части gen_servers возможностей, на самом деле очень часто не используют все из них. В вашем случае вы устанавливаете таймер только на init и используете handle_info для своей работы. Остальная часть gen_server - это просто неизменный шаблон.

  • Если позже вы захотите изменить такие параметры, как частота опроса, это легко добавить к этому.

  • gen_fsm используется гораздо реже, поскольку подходит только для довольно ограниченной модели и не очень гибок. Я использую его только тогда, когда он действительно соответствует 100% требованиям (что он делает почти никогда).

  • В случае, когда вам нужен простой простой сервер Erlang, вы можете использовать функции spawn в proc_lib, чтобы получить только минимальную функциональность для запуска под наблюдателем.

  • Интересный способ написать более естественный код Erlang и при этом иметь преимущества OTP: plain_fsm, здесь у вас есть преимущества избирательного приема и гибкой обработки сообщений, которые необходимы, особенно при обработке парных протоколов с приятными возможностями OTP.

Сказав все это: если бы я написал dir_watcher, я бы просто использовал gen_server и использовал только то, что мне нужно. Неиспользованная функциональность на самом деле ничего не стоит, и все понимают, что она делает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...