Есть ли способ заставить Apache Commons FileAlterationMonitor оповещать только один раз о пакете входящих файлов?

#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 для всех этих 500 onFileCreate событий в 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. Неплохо, похоже, это то, что я могу заставить работать, и думаю, что я следую всему этому. Файлы просто как бы заливаются, когда мы их получаем, поэтому мне, вероятно, придется поиграть с пороговым значением и посмотреть, какие предупреждения я получаю. Это определенно помогает мне достичь желаемого, так что большое спасибо! Я ценю это.