EnforcerRetriever { public CompletionStage<Contextual<WithDittoHeaders>> retrieve(final EntityIdWithResourceType entityKey, final BiFunction<Entry<EntityIdWithResourceType>, Entry<Enforcer>, CompletionStage<Contextual<WithDittoHeaders>>> handler) { return idCache.get(entityKey).thenCompose(enforcerKeyEntryOptional -> { if (enforcerKeyEntryOptional.isEmpty()) { LOGGER.info("Did not get id-cache value for entityKey <{}>.", entityKey); return handler.apply(Entry.nonexistent(), Entry.nonexistent()); } else { final Entry<EntityIdWithResourceType> enforcerKeyEntry = enforcerKeyEntryOptional.get(); if (enforcerKeyEntry.exists()) { final EntityIdWithResourceType enforcerKey = enforcerKeyEntry.getValueOrThrow(); final String resourceType = enforcerKey.getResourceType(); final Cache<EntityIdWithResourceType, Entry<Enforcer>> enforcerCache = enforcerCacheFunction.apply(resourceType); if (enforcerCache == null) { LOGGER.error("No enforcerCache for resource type: <{}>", resourceType); throw GatewayInternalErrorException.newBuilder() .build(); } return retrieveByEnforcerKey(enforcerKey, enforcerEntry -> handler.apply(enforcerKeyEntry, enforcerEntry)); } else { return handler.apply(enforcerKeyEntry, Entry.nonexistent()); } } }); } EnforcerRetriever(
            final Cache<EntityIdWithResourceType, Entry<EntityIdWithResourceType>> idCache,
            final Cache<EntityIdWithResourceType, Entry<Enforcer>> enforcerCache); private  EnforcerRetriever(
            final Cache<EntityIdWithResourceType, Entry<EntityIdWithResourceType>> idCache,
            final Function<String, Cache<EntityIdWithResourceType, Entry<Enforcer>>> enforcerCacheFunction);  EnforcerRetriever(
            final Cache<EntityIdWithResourceType, Entry<EntityIdWithResourceType>> idCache,
            final Map<String, Cache<EntityIdWithResourceType, Entry<Enforcer>>> enforcerCaches); CompletionStage<Contextual<WithDittoHeaders>> retrieve(final EntityIdWithResourceType entityKey,
            final BiFunction<Entry<EntityIdWithResourceType>, Entry<Enforcer>, CompletionStage<Contextual<WithDittoHeaders>>> handler); CompletionStage<Contextual<WithDittoHeaders>> retrieveByEnforcerKey(
            final EntityIdWithResourceType enforcerKey,
            final Function<Entry<Enforcer>, CompletionStage<Contextual<WithDittoHeaders>>> handler);  }
@Test public void verifyLookupRevealsInnerException() throws ExecutionException, InterruptedException { final DittoRuntimeException expectedException = DittoRuntimeException.newBuilder("this should be happening", HttpStatusCode.HTTPVERSION_NOT_SUPPORTED) .build(); final EntityIdWithResourceType entityId = EntityIdWithResourceType.of("any", DefaultEntityId.of("id")); when(idCache.get(any(EntityIdWithResourceType.class))).thenReturn( CompletableFuture.completedFuture(Optional.of(Entry.nonexistent()))); final CompletionStage<Contextual<WithDittoHeaders>> result = retriever.retrieve(entityId, (entityIdEntry, enforcerEntry) -> { throw expectedException; }); verify(idCache).get(entityId); verifyZeroInteractions(enforcerCache); verifyException(result, expectedException); }
@Test public void verifyLookupRevealsInnermostException() throws ExecutionException, InterruptedException { final DittoRuntimeException expectedException = DittoRuntimeException.newBuilder("this should be happening", HttpStatusCode.HTTPVERSION_NOT_SUPPORTED) .build(); final EntityIdWithResourceType entityId = EntityIdWithResourceType.of("any", DefaultEntityId.of("id")); final EntityIdWithResourceType innerEntityId = EntityIdWithResourceType.of("other", DefaultEntityId.of("randomId")); when(idCache.get(any(EntityIdWithResourceType.class))).thenReturn( CompletableFuture.completedFuture(Optional.of(Entry.permanent(innerEntityId)))); when(enforcerCache.get(any(EntityIdWithResourceType.class))).thenReturn( CompletableFuture.completedFuture(Optional.of(Entry.nonexistent()))); final CompletionStage<Contextual<WithDittoHeaders>> result = retriever.retrieve(entityId, (entityIdEntry, enforcerEntry) -> { throw expectedException; }); verify(idCache).get(entityId); verify(enforcerCache).get(innerEntityId); verifyException(result, expectedException); }