INT-4351: Add DiscardAwareFileListFilter

JIRA: https://jira.spring.io/browse/INT-4351

The `WatchService` reacts to the events in the file system and keep
track ove the events until we poll them, e.g. via `listEligibleFiles()`
in the `WatchServiceDirectoryScanner`.
On the other hand the `SourcePollingChannelAdapter` calls the mentioned
`listEligibleFiles()` according its polling period.
At this moment the `FileListFilter` is applied to the polled files.
It may happen that `LastModifiedFileListFilter` can't accept too young
files yet and they are lost for the future consideration.

* To allow, for example, to retain young files by the
`LastModifiedFileListFilter` judgment for the future cycles add
`DiscardAwareFileListFilter` with the `DiscardCallback` support.
The `WatchServiceDirectoryScanner` now registers such a callback into
the filter and stores discarded files into the `filesToPoll` queue
for the future poll cycle.

**Cherry-pick to 5.0**

Fix compilation warnings

* Replace `DiscardCallback` with the plain `Consumer`
* Ensure uniqueness in the `WatchServiceDirectoryScanner` internal
queue via a `Set` implementation, since discard callback may be called
several times for the same file from the `CompositeFileListFilter`
according to its nature
* Add JavaDocs and Docs

Change `@since` to `5.0.5`
This commit is contained in:
Artem Bilan
2018-03-29 17:37:24 -04:00
committed by Gary Russell
parent acd78a7f48
commit 0ef659b8a7
6 changed files with 135 additions and 28 deletions

View File

@@ -39,7 +39,9 @@ import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.file.filters.ChainFileListFilter;
import org.springframework.integration.file.filters.FileSystemPersistentAcceptOnceFileListFilter;
import org.springframework.integration.file.filters.LastModifiedFileListFilter;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
@@ -75,6 +77,7 @@ public class WatchServiceDirectoryScannerTests {
}
@Test
@SuppressWarnings("unchecked")
public void testWatchServiceDirectoryScanner() throws Exception {
FileReadingMessageSource fileReadingMessageSource = new FileReadingMessageSource();
fileReadingMessageSource.setDirectory(folder.getRoot());
@@ -86,7 +89,7 @@ public class WatchServiceDirectoryScannerTests {
final CountDownLatch removeFileLatch = new CountDownLatch(1);
FileSystemPersistentAcceptOnceFileListFilter filter =
FileSystemPersistentAcceptOnceFileListFilter fileSystemPersistentAcceptOnceFileListFilter =
new FileSystemPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "test") {
@Override
@@ -97,14 +100,24 @@ public class WatchServiceDirectoryScannerTests {
};
fileReadingMessageSource.setFilter(filter);
LastModifiedFileListFilter fileLastModifiedFileListFilter = new LastModifiedFileListFilter();
ChainFileListFilter<File> fileChainFileListFilter = new ChainFileListFilter<>();
fileChainFileListFilter.addFilters(fileLastModifiedFileListFilter, fileSystemPersistentAcceptOnceFileListFilter);
fileReadingMessageSource.setFilter(fileChainFileListFilter);
fileReadingMessageSource.afterPropertiesSet();
fileReadingMessageSource.start();
DirectoryScanner scanner = fileReadingMessageSource.getScanner();
assertThat(scanner.getClass().getName(),
containsString("FileReadingMessageSource$WatchServiceDirectoryScanner"));
// Files are skipped by the LastModifiedFileListFilter
List<File> files = scanner.listFiles(folder.getRoot());
assertEquals(0, files.size());
// Consider all the files as one day old
fileLastModifiedFileListFilter.setAge(-60 * 60 * 24);
files = scanner.listFiles(folder.getRoot());
assertEquals(3, files.size());
assertTrue(files.contains(top1));
assertTrue(files.contains(foo1));