FileWatchEventCoalescor extends EventCoalescor<FileWatchEvent> { public void post(final FileWatchEvent event) { synchronized (queue) { final FileWatchEventKey key = FileWatchEventKey.fromEvent(event); Deque<EventReference> fileEvents; if ((fileEvents = queue.get(key)) == null) { fileEvents = new ArrayDeque<>(); queue.put(key, fileEvents); EventReference reference = EventReference.of(key, event); fileEvents.add(reference); schedulePost(reference); return; } EventReference last = fileEvents.getLast(); if (!merge(last, event)) { EventReference reference = EventReference.of(key, event); fileEvents.add(reference); schedulePost(reference); } } } FileWatchEventCoalescor(EventBus eventBus, long coalescePeriod); static FileWatchEventCoalescor create(EventBus eventBus, long coalescePeriod); void post(final FileWatchEvent event);  }
@Test public void should_send_events() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_DELETE); watchEventCoalescor.post("tmp/test", StandardWatchEventKinds.ENTRY_MODIFY); watchEventCoalescor.post("tmp/another_file.txt", StandardWatchEventKinds.ENTRY_CREATE); assertThat(watchEventCoalescor.scheduledEvents).extracting("reference").extracting("path") .containsOnly( Paths.get("tmp/foo"), Paths.get("tmp/bar"), Paths.get("tmp/test"), Paths.get("tmp/another_file.txt") ); }
@Test public void should_merge_delete_with_create_events() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_DELETE); FileWatchEvent noise = watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); assertThat(watchEventCoalescor.removeNoise(noise)).isTrue(); assertThat(watchEventCoalescor.scheduledEvents).hasSize(1); FileWatchEvent event = watchEventCoalescor.scheduledEvents.get(0).getReference(); assertThat(event.getPath()).isEqualTo(Paths.get("tmp/foo")); assertThat(event.getKind()).isEqualTo(StandardWatchEventKinds.ENTRY_MODIFY); }
@Test public void should_merge_create_with_modify_events() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); FileWatchEvent noise = watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_MODIFY); assertThat(watchEventCoalescor.removeNoise(noise)).isTrue(); assertThat(watchEventCoalescor.scheduledEvents).hasSize(1); FileWatchEvent event = watchEventCoalescor.scheduledEvents.get(0).getReference(); assertThat(event.getPath()).isEqualTo(Paths.get("tmp/foo")); assertThat(event.getKind()).isEqualTo(StandardWatchEventKinds.ENTRY_CREATE); }
@Test public void should_remove_consecutive_create_and_delete_events() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); FileWatchEvent noise = watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_DELETE); assertThat(watchEventCoalescor.removeNoise(noise)).isTrue(); assertThat(watchEventCoalescor.scheduledEvents).hasSize(1); assertThat(watchEventCoalescor.scheduledEvents.get(0).isPresent()).isFalse(); }
@Test public void should_only_merge_consecutive_events_for_a_file() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_MODIFY); FileWatchEvent noise1 = watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_DELETE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_MODIFY); watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); assertThat(watchEventCoalescor.removeNoise(noise1)).isTrue(); assertThat(watchEventCoalescor.scheduledEvents).hasSize(4); assertThat(watchEventCoalescor.scheduledEvents).extracting("reference").extracting("kind") .containsExactly( StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE ); }
@Test public void should_merge_classic_idea_on_windows_behavior() { TestFileWatchEventCoalescor watchEventCoalescor = new TestFileWatchEventCoalescor(); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_DELETE); FileWatchEvent noise1 = watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/bar", StandardWatchEventKinds.ENTRY_CREATE); watchEventCoalescor.post("tmp/foo", StandardWatchEventKinds.ENTRY_MODIFY); assertThat(watchEventCoalescor.removeNoise(noise1)).isTrue(); assertThat(watchEventCoalescor.scheduledEvents).hasSize(1); FileWatchEvent event = watchEventCoalescor.scheduledEvents.get(0).getReference(); assertThat(event.getPath()).isEqualTo(Paths.get("tmp/foo")); assertThat(event.getKind()).isEqualTo(StandardWatchEventKinds.ENTRY_MODIFY); }