Skip to content

Commit

Permalink
Drop ResourceHandler.
Browse files Browse the repository at this point in the history
`ResourceHandler` has moved to `creek-service` repo. This decouples things. The initializer that a reduced-scope call back for resource creation.

BREAKING CHANGE: This is a braking change. Downstream projects won't build clean until they too are updated to work with this change.
  • Loading branch information
big-andy-coates committed Dec 21, 2023
1 parent dc6c9c1 commit 8981f29
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 89 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@
import org.creekservice.api.observability.logging.structured.StructuredLogger;
import org.creekservice.api.observability.logging.structured.StructuredLoggerFactory;
import org.creekservice.api.platform.metadata.ComponentDescriptor;
import org.creekservice.api.platform.metadata.OwnedResource;
import org.creekservice.api.platform.metadata.ResourceDescriptor;
import org.creekservice.api.platform.metadata.ResourceHandler;
import org.creekservice.internal.platform.resource.ComponentValidator;

/**
Expand All @@ -58,38 +58,42 @@ public final class ResourceInitializer {
private static final StructuredLogger LOGGER =
StructuredLoggerFactory.internalLogger(ResourceInitializer.class);

private final ResourceHandlers handlers;
private final ResourceCreator resourceCreator;
private final ComponentValidator componentValidator;

/** Type for retrieving resource handlers */
/** Type for ensuring external resources exist */
@FunctionalInterface
public interface ResourceHandlers {
public interface ResourceCreator {

/**
* Get the handler for a specific type
* Get the handler for a specific type.
*
* @param type the type
* @param <T> the type
* @return the handler
* <p>All {@code creatableResources} will be of the same type.
*
* @param creatableResources the resource instances to ensure exists and are initialized.
* Resources passed will be {@link ResourceDescriptor#isCreatable creatable}.
* @param <T> the creatable resource descriptor type
* @throws RuntimeException on unknown resource type
*/
<T extends ResourceDescriptor> ResourceHandler<T> get(Class<T> type);
<T extends ResourceDescriptor & OwnedResource> void ensure(
Collection<T> creatableResources);
}

/**
* Create an initializer instance.
*
* @param handlers accessor to resource handlers, as exposed by Creek extensions.
* @param resourceCreator callback used to ensure external resources exist, as exposed by Creek
* extensions.
* @return an initializer instance.
*/
public static ResourceInitializer resourceInitializer(final ResourceHandlers handlers) {
return new ResourceInitializer(handlers, new ComponentValidator());
public static ResourceInitializer resourceInitializer(final ResourceCreator resourceCreator) {
return new ResourceInitializer(resourceCreator, new ComponentValidator());
}

@VisibleForTesting
ResourceInitializer(
final ResourceHandlers handlers, final ComponentValidator componentValidator) {
this.handlers = requireNonNull(handlers, "handlers");
final ResourceCreator resourceCreator, final ComponentValidator componentValidator) {
this.resourceCreator = requireNonNull(resourceCreator, "resourceCreator");
this.componentValidator = requireNonNull(componentValidator, "componentValidator");
}

Expand Down Expand Up @@ -173,12 +177,14 @@ public void test(
ensureResources(stream);
}

@SuppressWarnings({"unchecked", "rawtypes"})
private void ensureResources(final Stream<List<ResourceDescriptor>> resGroups) {
resGroups
.peek(this::validateResourceGroup)
.map(this::creatableDescriptor)
.collect(groupingBy(this::resourceHandler))
.forEach(ResourceHandler::ensure);
.collect(groupingBy(Object::getClass))
.values()
.forEach(creatableResources -> resourceCreator.ensure((List) creatableResources));
}

private ResourceDescriptor creatableDescriptor(final List<ResourceDescriptor> resGroup) {
Expand Down Expand Up @@ -237,11 +243,6 @@ private <T extends ResourceDescriptor> void validateResourceGroup(final List<T>
}
}

@SuppressWarnings("unchecked")
private <T extends ResourceDescriptor> ResourceHandler<T> resourceHandler(final T resource) {
return handlers.get((Class<T>) resource.getClass());
}

private static String formatResource(final List<? extends ResourceDescriptor> descriptors) {
return descriptors.stream()
.map(ResourceInitializer::formatResource)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
import org.creekservice.api.platform.metadata.ComponentDescriptor;
import org.creekservice.api.platform.metadata.OwnedResource;
import org.creekservice.api.platform.metadata.ResourceDescriptor;
import org.creekservice.api.platform.metadata.ResourceHandler;
import org.creekservice.api.platform.metadata.SharedResource;
import org.creekservice.api.platform.metadata.UnownedResource;
import org.creekservice.internal.platform.resource.ComponentValidator;
Expand All @@ -58,9 +57,7 @@ class ResourceInitializerTest {
@Mock private ComponentValidator validator;
@Mock private ComponentDescriptor component0;
@Mock private ComponentDescriptor component1;
@Mock private ResourceInitializer.ResourceHandlers handlers;
@Mock private ResourceHandler<ResourceDescriptor> handlerA;
@Mock private ResourceHandler<ResourceDescriptor> handlerB;
@Mock private ResourceInitializer.ResourceCreator resourceCreator;

@Mock(extraInterfaces = SharedResource.class)
private ResourceA sharedResource1;
Expand All @@ -77,9 +74,7 @@ class ResourceInitializerTest {

@BeforeEach
void setUp() {
initializer = new ResourceInitializer(handlers, validator);

when(handlers.get(any())).thenReturn(handlerA);
initializer = new ResourceInitializer(resourceCreator, validator);

when(sharedResource1.id()).thenReturn(A1_ID);
when(ownedResource1.id()).thenReturn(A1_ID);
Expand Down Expand Up @@ -239,7 +234,7 @@ void shouldNotInitializeAnyResourceOnInitIfNoSharedResources() {
initializer.init(List.of(component0, component1));

// Then:
verify(handlers, never()).get(any());
verify(resourceCreator, never()).ensure(any());
}

@Test
Expand All @@ -254,7 +249,7 @@ void shouldNotInitializeAnyResourcesOnServiceIfNoOwnedResources() {
initializer.service(List.of(component0, component1));

// Then:
verify(handlerA, never()).ensure(any());
verify(resourceCreator, never()).ensure(any());
}

@Test
Expand All @@ -271,7 +266,7 @@ void shouldNotInitializeAnyResourcesOnTestIfNoUnownedResources() {
initializer.test(List.of(component0), List.of(component1));

// Then:
verify(handlerA, never()).ensure(any());
verify(resourceCreator, never()).ensure(any());
}

@Test
Expand All @@ -285,7 +280,7 @@ void shouldNotInitializeAnyResourcesOnTestIfNoUnownedResources() {
initializer.test(List.of(component0, component1), List.of());

// Then:
verify(handlerA, never()).ensure(any());
verify(resourceCreator, never()).ensure(any());
}

@Test
Expand All @@ -301,7 +296,7 @@ void shouldNotInitializeUnmanagedGroups() {
initializer.init(List.of(component0, component1));

// Then:
verify(handlers, never()).get(any());
verify(resourceCreator, never()).ensure(any());
}

@Test
Expand All @@ -325,6 +320,7 @@ void shouldThrowOnUncreatableResource() {
assertThat(e.getMessage(), containsString("unownedResource1"));
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test
void shouldEnsureSharedResource() {
// Given:
Expand All @@ -336,9 +332,10 @@ void shouldEnsureSharedResource() {
initializer.init(List.of(component0, component1));

// Then:
verify(handlerA).ensure(List.of(sharedResource1, sharedResource2));
verify(resourceCreator).ensure((List) List.of(sharedResource1, sharedResource2));
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test
void shouldEnsureOwnedResource() {
// Given:
Expand All @@ -350,9 +347,10 @@ void shouldEnsureOwnedResource() {
initializer.service(List.of(component0, component1));

// Then:
verify(handlerA).ensure(List.of(ownedResource1, ownedResource2));
verify(resourceCreator).ensure((List) List.of(ownedResource1, ownedResource2));
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test
void shouldEnsureUnownedResource() {
// Given:
Expand All @@ -365,14 +363,14 @@ void shouldEnsureUnownedResource() {
initializer.test(List.of(component0), List.of(component1));

// Then:
verify(handlerA).ensure(List.of(ownedResource2));
verify(resourceCreator).ensure((List) List.of(ownedResource2));
}

@Test
void shouldThrowIfEnsureThrows() {
// Given:
final RuntimeException expected = new RuntimeException("boom");
doThrow(expected).when(handlerA).ensure(any());
doThrow(expected).when(resourceCreator).ensure(any());
when(component0.resources()).thenReturn(Stream.of(ownedResource1));

// When:
Expand All @@ -384,32 +382,26 @@ void shouldThrowIfEnsureThrows() {
assertThat(e, is(sameInstance(expected)));
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test
void shouldEnsureGroupingByHandler() {
// Given
when(handlers.get(any()))
.thenAnswer(
inv ->
ResourceA.class.isAssignableFrom(inv.getArgument(0))
? handlerA
: handlerB);

final ResourceB ownedResourceB = resourceB(OwnedResource.class);
when(component0.resources()).thenReturn(Stream.of(ownedResource1, ownedResourceB));

// When:
initializer.service(List.of(component0));

// Then:
verify(handlerA).ensure(List.of(ownedResource1));
verify(handlerB).ensure(List.of(ownedResourceB));
verify(resourceCreator).ensure((List) List.of(ownedResource1));
verify(resourceCreator).ensure((List) List.of(ownedResourceB));
}

@Test
void shouldThrowOnUnknownResourceType() {
// Given:
final NullPointerException expected = new NullPointerException("unknown");
when(handlers.get(any())).thenThrow(expected);
doThrow(expected).when(resourceCreator).ensure(any());
when(component0.resources()).thenReturn(Stream.of(sharedResource1));

// When:
Expand All @@ -424,7 +416,7 @@ void shouldThrowOnUnknownResourceType() {
@Test
void shouldThrowOnInvalidComponentUsingActualValidator() {
// Given:
initializer = ResourceInitializer.resourceInitializer(handlers);
initializer = ResourceInitializer.resourceInitializer(resourceCreator);

// Then:
assertThrows(RuntimeException.class, () -> initializer.init(List.of(component0)));
Expand Down

0 comments on commit 8981f29

Please sign in to comment.