#java #apache-commons
#java #apache-commons
Вопрос:
Я отслеживаю несколько (около 15) путей для входящих файлов, используя Apache Commons FileAlterationMonitor. Эти входящие файлы могут поступать партиями по 1-500 файлов одновременно. У меня все настроено, и приложение отслеживает папки, как и ожидалось, я настроил его на опрос папок каждую минуту. Моя проблема в том, что, как и ожидалось, слушатель, которому я настроил оповещения для каждого входящего файла, когда все, что мне действительно нужно, и я хочу, это знать, когда поступает новая партия файлов. Итак, я хотел бы получать одно предупреждение, а не до 500 одновременно.
Есть ли у кого-нибудь идеи о том, как контролировать количество оповещений или получать только первое или последнее уведомление или что-то в этом роде? Я хотел бы придерживаться FileAlterationMonitor, если это вообще возможно, потому что он будет работать в течение длительных периодов, и насколько я могу судить по тестированию, это то, что он, похоже, не создает большой нагрузки на систему или замедляет работу остальной части приложения. Но я определенно открыт для других идей, если то, что я ищу, невозможно с FileAlterationMonitor.
public class FileMonitor{
private final String newDirectory;
private FileAlterationMonitor monitor;
private final Alerts gui;
private final String provider;
public FileMonitor (String d, Alerts g, String pro) throws Exception{
newDirectory = d;
gui = g;
provider = pro;
}
public void startMonitor() throws Exception{
// Directory to monitor
final File directory = new File(newDirectory);
// create new observer
FileAlterationObserver fao = new FileAlterationObserver(directory);
// add listener to observer
fao.addListener(new FileAlterationListenerImpl(gui, provider));
// wait 1 minute between folder polls.
monitor = new FileAlterationMonitor(60000);
monitor.addObserver(fao);
monitor.start();
}
}
public class FileAlterationListenerImpl implements FileAlterationListener{
private final Alerts gui;
private final String provider;
private final LogFiles monitorLogs;
public FileAlterationListenerImpl(Alerts g, String pro){
gui = g;
provider = pro;
monitorLogs = new LogFiles();
}
@Override
public void onStart(final FileAlterationObserver observer){
System.out.println("The FileListener has started on: " observer.getDirectory().getAbsolutePath());
}
@Override
public void onDirectoryCreate(File file) {
}
@Override
public void onDirectoryChange(File file) {
}
@Override
public void onDirectoryDelete(File file) {
}
@Override
public void onFileCreate(File file) {
try{
switch (provider){
case "Spectrum": gui.alertsAreaAppend("New/Updated schedules available for Spectrum zones!rn");
monitorLogs.appendNewLogging("New/Updated schedules available for Spectrum zones!rn");
break;
case "DirecTV ZTA": gui.alertsAreaAppend("New/Updated schedules available for DirecTV ZTA zones!rn");
monitorLogs.appendNewLogging("New/Updated schedules available for DirecTV ZTA zones!rn");
break;
case "DirecTV RSN": gui.alertsAreaAppend("New/Updated schedules available for DirecTV RSN zones!rn");
monitorLogs.appendNewLogging("New/Updated schedules available for DirecTV RSN zones!rn");
break;
case "Suddenlink": gui.alertsAreaAppend("New/Updated schedules available for Suddenlink zones!rn");
monitorLogs.appendNewLogging("New/Updated schedules available for Suddenlink zones!rn");
break;
}
}catch (IOException e){}
}
@Override
public void onFileChange(File file) {
}
Выше приведен класс FileMonitor и переопределенный FileAlterationListener, который у меня есть на данный момент.
Любые предложения будут с благодарностью приняты.
Комментарии:
1. У меня не так много знаний о
FileAlterationListener
, но я быстро провел некоторое тестирование. Предположим, у вас есть папка A, в которую будут поступать пакетные файлы. Вместо наблюдения A, если вы наблюдаете родительский элемент A, давайте вызовем это B, тогда вы получите одноonDirectoryChange
событие на B для всех этих 500onFileCreate
событий в A. Но вам придется переместить свойonFileCreate
imp вonDirectoryChange
метод.2. Вы могли бы реализовать FileAlterationListenerImpl, чтобы он игнорировал вызовы onFileCreate(), когда последний обработанный файл был «менее n секунд назад». Установите «long lastFileProcessedAt» и установите значение «Long. MIN_VALUE» (таким образом, срабатывает первое уведомление). Затем, когда вызывается onFileCreate — if (System.currentTimeMillis() — lastFileProcessedAt < ПОРОГОВОЕ ЗНАЧЕНИЕ), возвращает. Помните, установите lastFileProcessedAt в System.currentTimeMillis() при обработке файла. * Только что видел, что это для каждого «провайдера», так что, возможно, Map<String, Long> где key = provider. Если это работоспособное решение, я предоставлю код в ответе!
3. @NotaJD — На самом деле я рассматривал что-то очень похожее на это, но не был уверен, как это правильно реализовать. Ваше решение определенно звучит работоспособно, и я был бы очень признателен, если бы вы посмотрели, как вы это сделаете.
4. @SojitJoshi Я также рассматривал возможность сделать это и фактически реализовал такую версию. Но по какой-то причине используемый нами файловый сервер не обновляет временные метки «родительских» папок при изменении «дочерней» папки, поэтому это не сработало так, как я надеялся, что это будет.
5. @ThomasHoppenreys уверен — ожидание производственного релиза для завершения прямо сейчас, так что пришлось поторопиться. Смотрите ниже!
Ответ №1:
Вот быстрая и грубая реализация:
public class FileAlterationListenerAlterThrottler {
private static final int DEFAULT_THRESHOLD_MS = 5000;
private final int thresholdMs;
private final Map<String, Long> providerLastFileProcessedAt = new HashMap<>();
public FileAlterationListenerAlterThrottler() {
this(DEFAULT_THRESHOLD_MS);
}
public FileAlterationListenerAlterThrottler(int thresholdMs) {
this.thresholdMs = thresholdMs;
}
public synchronized boolean shouldAlertFor(String provider) {
long now = System.currentTimeMillis();
long last = providerLastFileProcessedAt.computeIfAbsent(provider, x -> 0l);
if (now - last < thresholdMs) {
return false;
}
providerLastFileProcessedAt.put(provider, now);
return true;
}
}
И более быстрый и грубый драйвер:
public class Test {
public static void main(String[] args) throws Exception {
int myThreshold = 1000;
FileAlterationListenerAlterThrottler throttler = new FileAlterationListenerAlterThrottler(myThreshold);
for (int i = 0; i < 3; i ) {
doIt(throttler);
}
Thread.sleep(1500);
doIt(throttler);
}
private static void doIt(FileAlterationListenerAlterThrottler throttler) {
boolean shouldAlert = throttler.shouldAlertFor("Some Provider");
System.out.println("Time now: " System.currentTimeMillis());
System.out.println("Should alert? " shouldAlert);
System.out.println();
}
}
Выдает:
Time now: 1553739126557
Should alert? true
Time now: 1553739126557
Should alert? false
Time now: 1553739126557
Should alert? false
Time now: 1553739128058
Should alert? true
Комментарии:
1. Неплохо, похоже, это то, что я могу заставить работать, и думаю, что я следую всему этому. Файлы просто как бы заливаются, когда мы их получаем, поэтому мне, вероятно, придется поиграть с пороговым значением и посмотреть, какие предупреждения я получаю. Это определенно помогает мне достичь желаемого, так что большое спасибо! Я ценю это.