@Test public void announcesNoMeaningfulChangesWhenNoSemanticChanges() throws Exception { Resource configurationFile = mockResource("/styx/config", new ByteArrayInputStream(originalContent)); registry = new FileBackedRegistry<>(configurationFile, bytes -> ImmutableList.of(backendService), any -> true); registry.addListener(listener); await(registry.reload()); verify(listener).onChange(eq(changeSet().added(backendService).build())); when(configurationFile.inputStream()).thenReturn(new ByteArrayInputStream(newContent)); ReloadResult result = registry.reload().get(); assertThat(result, is(unchanged("timestamp=NA, md5-hash=24996b9d53b21a60c35dcb7ca3fb331a, No semantic changes."))); verify(listener).onChange(eq(changeSet().added(backendService).build())); }
@Override public CompletableFuture<ReloadResult> reload() { return supplyAsync(() -> { byte[] content = readFile(); HashCode hashCode = md5().hashBytes(content); String modifyTime = fileModificationTime().map(FileTime::toString).orElse("NA"); String logPrefix = format("timestamp=%s, md5-hash=%s", modifyTime, hashCode); if (hashCode.equals(fileHash)) { LOG.info("Not reloading {} as content did not change", configurationFile.absolutePath()); return unchanged(format("%s, Identical file content.", logPrefix)); } else { try { boolean changesPerformed = updateResources(content, hashCode); if (!changesPerformed) { LOG.info("Not firing change event for {} as content was not semantically different", configurationFile.absolutePath()); return unchanged(format("%s, No semantic changes.", logPrefix)); } else { LOG.debug("Changes applied!"); return reloaded(format("%s, File reloaded.", logPrefix)); } } catch (Exception e) { if (!"Resource constraint failure".equals(e.getMessage())) { LOG.error("Not reloading {} as there was an error reading content", configurationFile.absolutePath(), e); } return failed(format("%s, Reload failure.", logPrefix), e); } } }, newSingleThreadExecutor()); }
FileBackedRegistry extends AbstractRegistry<T> { @Override public CompletableFuture<ReloadResult> reload() { return supplyAsync(() -> { byte[] content = readFile(); HashCode hashCode = md5().hashBytes(content); String modifyTime = fileModificationTime().map(FileTime::toString).orElse("NA"); String logPrefix = format("timestamp=%s, md5-hash=%s", modifyTime, hashCode); if (hashCode.equals(fileHash)) { LOG.info("Not reloading {} as content did not change", configurationFile.absolutePath()); return unchanged(format("%s, Identical file content.", logPrefix)); } else { try { boolean changesPerformed = updateResources(content, hashCode); if (!changesPerformed) { LOG.info("Not firing change event for {} as content was not semantically different", configurationFile.absolutePath()); return unchanged(format("%s, No semantic changes.", logPrefix)); } else { LOG.debug("Changes applied!"); return reloaded(format("%s, File reloaded.", logPrefix)); } } catch (Exception e) { if (!"Resource constraint failure".equals(e.getMessage())) { LOG.error("Not reloading {} as there was an error reading content", configurationFile.absolutePath(), e); } return failed(format("%s, Reload failure.", logPrefix), e); } } }, newSingleThreadExecutor()); } }
FileBackedRegistry extends AbstractRegistry<T> { @Override public CompletableFuture<ReloadResult> reload() { return supplyAsync(() -> { byte[] content = readFile(); HashCode hashCode = md5().hashBytes(content); String modifyTime = fileModificationTime().map(FileTime::toString).orElse("NA"); String logPrefix = format("timestamp=%s, md5-hash=%s", modifyTime, hashCode); if (hashCode.equals(fileHash)) { LOG.info("Not reloading {} as content did not change", configurationFile.absolutePath()); return unchanged(format("%s, Identical file content.", logPrefix)); } else { try { boolean changesPerformed = updateResources(content, hashCode); if (!changesPerformed) { LOG.info("Not firing change event for {} as content was not semantically different", configurationFile.absolutePath()); return unchanged(format("%s, No semantic changes.", logPrefix)); } else { LOG.debug("Changes applied!"); return reloaded(format("%s, File reloaded.", logPrefix)); } } catch (Exception e) { if (!"Resource constraint failure".equals(e.getMessage())) { LOG.error("Not reloading {} as there was an error reading content", configurationFile.absolutePath(), e); } return failed(format("%s, Reload failure.", logPrefix), e); } } }, newSingleThreadExecutor()); } private  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier, Predicate<Collection<T>> resourceConstraint); @VisibleForTesting  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier);  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Predicate<Collection<T>> resourceConstraint); }
FileBackedRegistry extends AbstractRegistry<T> { @Override public CompletableFuture<ReloadResult> reload() { return supplyAsync(() -> { byte[] content = readFile(); HashCode hashCode = md5().hashBytes(content); String modifyTime = fileModificationTime().map(FileTime::toString).orElse("NA"); String logPrefix = format("timestamp=%s, md5-hash=%s", modifyTime, hashCode); if (hashCode.equals(fileHash)) { LOG.info("Not reloading {} as content did not change", configurationFile.absolutePath()); return unchanged(format("%s, Identical file content.", logPrefix)); } else { try { boolean changesPerformed = updateResources(content, hashCode); if (!changesPerformed) { LOG.info("Not firing change event for {} as content was not semantically different", configurationFile.absolutePath()); return unchanged(format("%s, No semantic changes.", logPrefix)); } else { LOG.debug("Changes applied!"); return reloaded(format("%s, File reloaded.", logPrefix)); } } catch (Exception e) { if (!"Resource constraint failure".equals(e.getMessage())) { LOG.error("Not reloading {} as there was an error reading content", configurationFile.absolutePath(), e); } return failed(format("%s, Reload failure.", logPrefix), e); } } }, newSingleThreadExecutor()); } private  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier, Predicate<Collection<T>> resourceConstraint); @VisibleForTesting  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier);  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Predicate<Collection<T>> resourceConstraint); String fileName(); @Override CompletableFuture<ReloadResult> reload(); }
FileBackedRegistry extends AbstractRegistry<T> { @Override public CompletableFuture<ReloadResult> reload() { return supplyAsync(() -> { byte[] content = readFile(); HashCode hashCode = md5().hashBytes(content); String modifyTime = fileModificationTime().map(FileTime::toString).orElse("NA"); String logPrefix = format("timestamp=%s, md5-hash=%s", modifyTime, hashCode); if (hashCode.equals(fileHash)) { LOG.info("Not reloading {} as content did not change", configurationFile.absolutePath()); return unchanged(format("%s, Identical file content.", logPrefix)); } else { try { boolean changesPerformed = updateResources(content, hashCode); if (!changesPerformed) { LOG.info("Not firing change event for {} as content was not semantically different", configurationFile.absolutePath()); return unchanged(format("%s, No semantic changes.", logPrefix)); } else { LOG.debug("Changes applied!"); return reloaded(format("%s, File reloaded.", logPrefix)); } } catch (Exception e) { if (!"Resource constraint failure".equals(e.getMessage())) { LOG.error("Not reloading {} as there was an error reading content", configurationFile.absolutePath(), e); } return failed(format("%s, Reload failure.", logPrefix), e); } } }, newSingleThreadExecutor()); } private  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier, Predicate<Collection<T>> resourceConstraint); @VisibleForTesting  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Supplier<FileTime> modifyTimeSupplier);  FileBackedRegistry(Resource configurationFile, Reader<T> reader, Predicate<Collection<T>> resourceConstraint); String fileName(); @Override CompletableFuture<ReloadResult> reload();  }