StringInterningLayer { protected CompletableFuture<ResolverResult> intern(@Nonnull FDBRecordContext context, @Nonnull final String toIntern) { CompletableFuture<Optional<ResolverResult>> readResult; synchronized (this) { readResult = read(context, toIntern); } return readResult .thenApply(maybeRead -> maybeRead.map(CompletableFuture::completedFuture)) .thenCompose(value -> value.orElseGet(() -> createMapping(context, toIntern, null))); } StringInterningLayer(@Nonnull Subspace baseSubspace);  StringInterningLayer(@Nonnull Subspace baseSubspace, boolean isRootLevel); private  StringInterningLayer(@Nonnull Subspace mappingSubspace,
                                 @Nonnull Subspace reverseMappingSubspace,
                                 @Nonnull Subspace counterSubspace,
                                 boolean isRootLevel);   }
@Test void testInterning() { final ResolverResult internedValue; try (FDBRecordContext context = database.openContext()) { StringInterningLayer interningLayer = new StringInterningLayer(testSubspace); internedValue = interningLayer.intern(context, "a-string").join(); for (int i = 0; i < 5; i++) { ResolverResult currentCall = interningLayer.intern(context, "a-string").join(); assertThat("we see the same interned value for subsequent calls in the transaction", currentCall, is(internedValue)); } context.commit(); } try (FDBRecordContext context = database.openContext()) { StringInterningLayer interningLayer = new StringInterningLayer(testSubspace); for (int i = 0; i < 5; i++) { ResolverResult currentCall = interningLayer.intern(context, "a-string").join(); assertThat("we see the same interned value for subsequent transactions", currentCall, is(internedValue)); } } }
@Test void testInterningConcurrent() { Map<String, Long> allocations; try (FDBRecordContext context = database.openContext()) { StringInterningLayer interningLayer = new StringInterningLayer(testSubspace); List<CompletableFuture<Pair<String, Long>>> futures = IntStream.range(0, 50) .mapToObj(i -> String.format("intern-%d", i)) .map(value -> interningLayer.intern(context, value).thenApply(interned -> Pair.of(value, interned.getValue()))) .collect(Collectors.toList()); allocations = AsyncUtil.getAll(futures).join().stream() .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); for (int i = 0; i < 50; i++) { String toIntern = "intern-" + i; Long value = interningLayer.intern(context, toIntern).join().getValue(); assertThat("value is in mapping", allocations.get(toIntern), is(value)); } } }