JsonFileBasedPersister { public synchronized void saveInIndex(Path metadataPath, T content) throws IOException { Path indexPath = jsonFile(metadataPath, INDEX_METADATA); Map<String, String> index = loadIndex(indexPath); try { if (getUUIDIfExist(content) != null) { index.put(getUUIDIfExist(content), content.getId()); } writeIndexFile(indexPath, index); } catch (JsonGenerationException e) { logger.error(format("Cannot generate index for file %s. Maybe a migration is required.", content.getId())); } } JsonFileBasedPersister(JacksonObjectMapper objectMapper, BeanValidator validator); void save(Path directory, T content); Path updateMetadata(Path directory, T content); synchronized void saveInIndex(Path metadataPath, T content); void delete(Path directory, T content); Path jsonFile(Path directory, String id); synchronized void refreshIndexing(Path metadataFolder, List<T> pages); static final String INDEX_METADATA; }
@Test public void should_support_parrelel_index_saves() throws Exception { Page page1 = PageBuilder.aPage().withUUID("baz-uuid").withName("baz").withId("baz-id").build(); Page page2 = PageBuilder.aPage().withUUID("foo-uuid").withName("foo").withId("foo-id").build(); JsonFileBasedPersister<Page> pageRepository = new JsonFileBasedPersister<Page>(objectMapper, validator); Path metadataFolder = repoDirectory.resolve(".metadata"); metadataFolder.toFile().mkdir(); new Thread(() -> { try { pageRepository.saveInIndex(metadataFolder, page2); } catch (IOException e) { throw new RuntimeException(e); } }).start(); new Thread(() -> { try { pageRepository.saveInIndex(metadataFolder, page1); } catch (IOException e) { throw new RuntimeException(e); } }).start(); Awaitility.await() .atMost(3, TimeUnit.SECONDS) .untilAsserted(new ThrowingRunnable() { @Override public void run() throws Throwable { String index = new String(readAllBytes(metadataFolder.resolve(".index.json"))); assertThat(index).contains("\"baz-uuid\":\"baz-id\"").contains("\"foo-uuid\":\"foo-id\""); } }); }