В 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
и использовал только то, что мне нужно. Неиспользованная функциональность на самом деле ничего не стоит, и все понимают, что она делает.