From 5d83d45b89839e2cc14b632562a5bd8c65e76117 Mon Sep 17 00:00:00 2001 From: Michael Schnell Date: Sun, 31 Dec 2023 11:49:20 +0100 Subject: [PATCH] Removed HTTP projection admin in favour of the GRPC variant --- admin/README.md | 3 - admin/pom.xml | 182 ------------ .../admin/HttpProjectionAdminEventStore.java | 269 ------------------ .../HttpProjectionAdminEventStoreIT.java | 94 ------ pom.xml | 3 +- 5 files changed, 1 insertion(+), 550 deletions(-) delete mode 100644 admin/README.md delete mode 100644 admin/pom.xml delete mode 100644 admin/src/main/java/org/fuin/esc/admin/HttpProjectionAdminEventStore.java delete mode 100644 admin/src/test/java/org/fuin/esc/admin/HttpProjectionAdminEventStoreIT.java diff --git a/admin/README.md b/admin/README.md deleted file mode 100644 index 00817181..00000000 --- a/admin/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# esc-http-admin -HTTP based implementation of the projection admin API. - diff --git a/admin/pom.xml b/admin/pom.xml deleted file mode 100644 index 6df6c0ff..00000000 --- a/admin/pom.xml +++ /dev/null @@ -1,182 +0,0 @@ - - - - 4.0.0 - - - org.fuin.esc - esc-parent - 0.7.0-SNAPSHOT - - - esc-http-admin - jar - HTTP based implementation of the projection administration API. - - - - - - - org.fuin.esc - esc-api - - - - org.fuin.esc - esc-spi - - - - jakarta.validation - jakarta.validation-api - true - - - - org.slf4j - slf4j-api - - - - - - org.junit.jupiter - junit-jupiter - test - - - - org.assertj - assertj-core - test - - - - nl.jqno.equalsverifier - equalsverifier - test - - - - ch.qos.logback - logback-classic - test - - - - org.hibernate.validator - hibernate-validator - test - - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - - - - org.apache.maven.plugins - maven-source-plugin - - - - org.apache.maven.plugins - maven-javadoc-plugin - - - - org.apache.maven.plugins - maven-jar-plugin - - - **/* - - - - org.fuin.esc.prjadmin - - - - - - - org.apache.maven.plugins - maven-jdeps-plugin - - - - org.apache.maven.plugins - maven-failsafe-plugin - - - - io.fabric8 - docker-maven-plugin - - - - - eventstore/eventstore:${eventstore.version} - - - bridge - - - 1113:1113 - 2113:2113 - - - TRUE - All - true - /tmp/log-eventstore - - - false - - - - http://localhost:2113/web/index.html#/ - GET - - - - - - - - - - - - start-images - pre-integration-test - - start - - - - stop-images - post-integration-test - - stop - - - - - - - - - - - diff --git a/admin/src/main/java/org/fuin/esc/admin/HttpProjectionAdminEventStore.java b/admin/src/main/java/org/fuin/esc/admin/HttpProjectionAdminEventStore.java deleted file mode 100644 index 9da6d7fc..00000000 --- a/admin/src/main/java/org/fuin/esc/admin/HttpProjectionAdminEventStore.java +++ /dev/null @@ -1,269 +0,0 @@ -package org.fuin.esc.admin; - -import jakarta.annotation.Nullable; -import jakarta.validation.constraints.NotNull; -import org.fuin.esc.api.*; -import org.fuin.esc.spi.ProjectionJavaScriptBuilder; -import org.fuin.esc.spi.TenantStreamId; -import org.fuin.objects4j.common.ConstraintViolationException; -import org.fuin.objects4j.common.Contract; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.net.URI; -import java.net.URL; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.time.temporal.ChronoUnit; -import java.util.Arrays; -import java.util.List; - -/** - * HTTP based eventstore projection admin implementation. - */ -public final class HttpProjectionAdminEventStore implements ProjectionAdminEventStore { - - private static final Logger LOG = LoggerFactory.getLogger(HttpProjectionAdminEventStore.class); - - private final HttpClient httpClient; - - private final URL url; - - private final TenantId tenantId; - - private final Duration timeout; - - /** - * Constructor with mandatory data. - * - * @param httpClient HTTP client to use. - * @param url Eventstore base URL like "http://127.0.0.1:2113". - */ - public HttpProjectionAdminEventStore(@NotNull final HttpClient httpClient, - @NotNull final URL url) { - this(httpClient, url, null, null); - } - - /** - * Constructor with all data. - * - * @param httpClient HTTP client to use. - * @param url Eventstore base URL like "http://127.0.0.1:2113". - * @param tenantId Tenant ID or {@literal null}. - * @param timeout Timeout to use for connections or {@literal null} (defaults to 10 seconds). - */ - public HttpProjectionAdminEventStore(@NotNull final HttpClient httpClient, - @NotNull final URL url, - @Nullable final TenantId tenantId, - @Nullable final Duration timeout) { - Contract.requireArgNotNull("httpClient", httpClient); - Contract.requireArgNotNull("url", url); - this.httpClient = httpClient; - this.url = url; - this.tenantId = tenantId; - this.timeout = timeout == null ? Duration.of(10, ChronoUnit.SECONDS) : timeout; - } - - @Override - public ProjectionAdminEventStore open() { - // Do nothing - return this; - } - - @Override - public void close() { - // Do nothing - } - - @Override - public boolean projectionExists(StreamId projectionId) { - Contract.requireArgNotNull("projectionId", projectionId); - requireProjection(projectionId); - - final TenantStreamId pid = new TenantStreamId(tenantId, projectionId); - final String msg = "projectionExists(" + pid + ")"; - - final URI uri = URI.create(url.toString() + "/projection/" + pid.asString() + "/state"); - - final HttpRequest request = HttpRequest.newBuilder().uri(uri) - .setHeader("Accept", "application/json") - .timeout(timeout) - .GET() - .build(); - LOG.debug("{} REQUEST: {}", msg, request); - try { - final HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - LOG.debug("{} RESPONSE: {}", msg, response.statusCode()); - if (response.statusCode() == 404) { - return false; - } - if (response.statusCode() == 200) { - return true; - } - throw new RuntimeException(msg + " [Status=" + response.statusCode() + "]"); - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(msg, ex); - } catch (final IOException ex) { - throw new RuntimeException(msg, ex); - } - - } - - @Override - public void enableProjection(StreamId projectionId) throws StreamNotFoundException { - enableDisable(new TenantStreamId(tenantId, projectionId), "enable"); - } - - @Override - public void disableProjection(StreamId projectionId) throws StreamNotFoundException { - enableDisable(new TenantStreamId(tenantId, projectionId), "disable"); - } - - @Override - public void createProjection(StreamId projectionId, boolean enable, @NotNull TypeName... eventType) throws StreamAlreadyExistsException { - Contract.requireArgNotNull("eventType", eventType); - createProjection(projectionId, enable, Arrays.asList(eventType)); - } - - @Override - public void createProjection(StreamId projectionId, boolean enable, List eventTypes) throws StreamAlreadyExistsException { - Contract.requireArgNotNull("projectionId", projectionId); - Contract.requireArgNotNull("eventTypes", eventTypes); - requireProjection(projectionId); - - final TenantStreamId pid = new TenantStreamId(tenantId, projectionId); - final String msg = "createProjection(" + pid + "," + enable + type2str(eventTypes) + ")"; - - - final URI uri = URI.create(url.toString() + "/projections/continuous?name=" + pid.asString() + "&emit=yes&checkpoints=yes&enabled=" + yesNo(enable)); - - final String javascript = new ProjectionJavaScriptBuilder(pid).types(eventTypes).build(); - final HttpRequest request = HttpRequest.newBuilder().uri(uri) - .setHeader("Accept", "application/json") - .setHeader("Content-Type", "application/json; charset=utf-8") - .timeout(timeout) - .POST(HttpRequest.BodyPublishers.ofString(javascript, StandardCharsets.UTF_8)) - .build(); - - LOG.debug("{} REQUEST: {}", msg, request); - - try { - final HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - LOG.debug("{} RESPONSE: {}", msg, response.statusCode()); - if (response.statusCode() == 201) { - // CREATED - return; - } - throw new RuntimeException(msg + " [Status=" + response.statusCode() + "]"); - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(msg, ex); - } catch (final IOException ex) { - throw new RuntimeException(msg, ex); - } - } - - @Override - public void deleteProjection(StreamId projectionId) throws StreamNotFoundException { - Contract.requireArgNotNull("projectionId", projectionId); - requireProjection(projectionId); - - disableProjection(projectionId); - - final TenantStreamId pid = new TenantStreamId(tenantId, projectionId); - final String msg = "deleteProjection(" + pid + ")"; - - final URI uri = URI.create(url.toString() + "/projection/" + projectionId.asString() + "?deleteCheckpointStream=yes&deleteStateStream=yes&deleteEmittedStreams=yes"); - - final HttpRequest request = HttpRequest.newBuilder().uri(uri).timeout(timeout).DELETE().build(); - LOG.debug("{} DELETE: {}", msg, request); - try { - final HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - LOG.debug("{} RESPONSE: {}", msg, response.statusCode()); - if (response.statusCode() == 200) { - return; - } - if (response.statusCode() == 404) { - throw new StreamNotFoundException(pid); - } - throw new RuntimeException(msg + " [Status=" + response.statusCode() + "]"); - - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(msg, ex); - } catch (final IOException ex) { - throw new RuntimeException(msg, ex); - } - } - - private void enableDisable(final TenantStreamId projectionId, final String action) { - - Contract.requireArgNotNull("projectionId", projectionId); - requireProjection(projectionId); - - final String msg = action + "Projection(" + projectionId + ")"; - - final URI uri = URI.create(url.toString() + "/projection/" + projectionId.asString() + "/command/" + action); - - final HttpRequest request = HttpRequest.newBuilder().uri(uri) - .setHeader("Accept", "application/json") - .setHeader("Content-Type", "application/json; charset=utf-8") - .timeout(timeout) - .POST(HttpRequest.BodyPublishers.noBody()) - .build(); - LOG.debug("{} REQUEST: {}", msg, request); - try { - final HttpResponse response = httpClient.send(request, HttpResponse.BodyHandlers.ofString()); - LOG.debug("{} RESPONSE: {}", msg, response.statusCode()); - if (response.statusCode() == 200) { - return; - } - if (response.statusCode() == 404) { - throw new StreamNotFoundException(projectionId); - } - throw new RuntimeException(msg + " [Status=" + response.statusCode() + "]"); - } catch (final InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new RuntimeException(msg, ex); - } catch (final IOException ex) { - throw new RuntimeException(msg, ex); - } - } - - /** - * Converts a boolean value to "yes" or "no". - * - * @param b Boolean value to convert. - * @return String "yes" or "no". - */ - static String yesNo(final boolean b) { - if (b) { - return "yes"; - } - return "no"; - } - - static String type2str(final List eventTypes) { - if (eventTypes == null) { - return ""; - } - final StringBuilder sb = new StringBuilder(); - for (final TypeName eventType : eventTypes) { - sb.append(","); - sb.append(eventType.asBaseType()); - } - return sb.toString(); - } - - static void requireProjection(final StreamId projectionId) { - if (!projectionId.isProjection()) { - throw new ConstraintViolationException("The stream identifier is not a projection id"); - } - } - -} diff --git a/admin/src/test/java/org/fuin/esc/admin/HttpProjectionAdminEventStoreIT.java b/admin/src/test/java/org/fuin/esc/admin/HttpProjectionAdminEventStoreIT.java deleted file mode 100644 index 447fbfe7..00000000 --- a/admin/src/test/java/org/fuin/esc/admin/HttpProjectionAdminEventStoreIT.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.fuin.esc.admin; - -import org.fuin.esc.api.ProjectionStreamId; -import org.fuin.esc.api.TypeName; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.net.Authenticator; -import java.net.MalformedURLException; -import java.net.PasswordAuthentication; -import java.net.URL; -import java.net.http.HttpClient; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests the {@link HttpProjectionAdminEventStore} class. - */ -class HttpProjectionAdminEventStoreIT { - - private static HttpClient httpClient; - - private HttpProjectionAdminEventStore testee; - - @BeforeAll - static void beforeAll() { - httpClient = HttpClient.newBuilder() - .authenticator(new Authenticator() { - @Override - protected PasswordAuthentication getPasswordAuthentication() { - return new PasswordAuthentication("admin", "changeit".toCharArray()); - } - }) - .build(); - } - - @BeforeEach - void beforeEach() throws MalformedURLException { - testee = new HttpProjectionAdminEventStore(httpClient, new URL("http://127.0.0.1:2113")); - } - - @Test - void testProjectionNotExists() { - assertThat(testee.projectionExists(new ProjectionStreamId("http-test-not-existing"))).isFalse(); - } - - @Test - void testEnableDisableProjection() { - - // GIVEN - final ProjectionStreamId projectionId = new ProjectionStreamId("http-test-disabled"); - testee.createProjection(projectionId, false, new TypeName("one"), new TypeName("two")); - - // WHEN - testee.enableProjection(projectionId); - - // THEN - // TODO assertThat(testee.projectionEnabled()).isTrue(); - - } - - @Test - void testCreateAndExistsProjection() { - - // GIVEN - final ProjectionStreamId projectionId = new ProjectionStreamId("http-test-create"); - assertThat(testee.projectionExists(projectionId)).isFalse(); - - // WHEN - testee.createProjection(projectionId, true, new TypeName("one"), new TypeName("two")); - - // THEN - assertThat(testee.projectionExists(projectionId)).isTrue(); - - } - - @Test - void testDeleteProjection() { - - // GIVEN - final ProjectionStreamId projectionId = new ProjectionStreamId("http-test-delete"); - testee.createProjection(projectionId, false, new TypeName("one"), new TypeName("two")); - assertThat(testee.projectionExists(projectionId)).isTrue(); - - // WHEN - testee.deleteProjection(projectionId); - - // THEN - assertThat(testee.projectionExists(projectionId)).isFalse(); - - } - -} diff --git a/pom.xml b/pom.xml index ae75df61..9c714a3a 100644 --- a/pom.xml +++ b/pom.xml @@ -189,7 +189,7 @@ net.javacrumbs.json-unit json-unit-fluent - 2.38.0 + 3.0.0 @@ -332,7 +332,6 @@ api spi - admin mem jpa eshttp