Вот как я решил свои проблемы.
Обратите внимание, что у меня была эта проблема в нескольких областях моего рабочего процесса. во-первых, мне нужно было отслеживать новые файлы в каталоге с моим приложением и следить за тем, чтобы они были завершены, и т. д. во-вторых, мне приходилось загружать файлы в каталог, за которым следит другая программа, а) у меня нет контроль, и б) очень архаичен и не выполняет никакой проверки.
Для решения первой задачи:
В моем запланированном задании я просканировал каталог на наличие всех файлов, затем сгенерировал хэш md5 для каждого файла и сохранил его в таблице в базе данных вместе с путем к файлу.
В следующий раз, когда мое запланированное задание будет выполнено (через 1 минуту), я извлекаю все строки из базы данных (путь к файлу и хэш), проверяю, существует ли файл, и затем снова генерирую хеш md5. Если файл существует и хэш-код совпадает, я выполняю обработку файла (и удаляю его из каталога). В случае сбоя одного из этих двух файлов я просто перехожу к следующему файлу в цикле.
После того, как все файлы обработаны, я обрезаю таблицу, которая проиндексировала файлы, и затем переиндексирую все файлы, снова сохраняя их в базе данных. Минуту спустя моя работа начинается снова, потребляя файлы из индекса.
Таким образом, я никогда не работаю с файлами, которые я не проиндексировал с предыдущего запуска задания. Я полагаю, можно с уверенностью предположить, что если хэш файла не изменился в течение 1 минуты, то файл завершается передача, и я могу использовать его.
Для решения второй задачи:
Чтобы гарантировать, что другая часть программного обеспечения не будет использовать файл, который мог находиться в процессе загрузки, я просто создал на сервере другой каталог, который программа не отслеживала, и загрузил туда файлы. Когда передача файлов была завершена, я выполнил команду перемещения, чтобы переместить файлы в отслеживаемый каталог, и, поскольку перемещение - это атомарная операция в файловой системе, поэтому оно безопасно от состояния гонки.