diff --git a/pom.xml b/pom.xml
index 43df782..3603640 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
UTF-8
quarkus-bom
io.quarkus.platform
- 3.6.5
+ 3.7.2
3.1.2
diff --git a/src/main/java/org/alliancegenome/mati/controller/AdminResource.java b/src/main/java/org/alliancegenome/mati/controller/AdminResource.java
index a86ed82..3d30752 100644
--- a/src/main/java/org/alliancegenome/mati/controller/AdminResource.java
+++ b/src/main/java/org/alliancegenome/mati/controller/AdminResource.java
@@ -2,27 +2,34 @@
import jakarta.enterprise.context.RequestScoped;
import jakarta.inject.Inject;
+import jakarta.transaction.Transactional;
import jakarta.ws.rs.core.Response;
import org.alliancegenome.mati.configuration.ErrorResponse;
-import org.alliancegenome.mati.entity.SubdomainEntity;
import org.alliancegenome.mati.interfaces.AdminRESTInterface;
-import org.alliancegenome.mati.repository.SubdomainRepository;
import org.alliancegenome.mati.repository.SubdomainSequenceRepository;
+import org.alliancegenome.mati.rolldownrepository.DBRoller;
+import org.eclipse.microprofile.config.inject.ConfigProperty;
+import java.util.List;
import java.util.Map;
/**
- * Controller for administrative endpoints
+ * Controller for:
+ * getting the current values of the counters (subdomains)
+ * and rolling down the MaTI database
*/
@RequestScoped
public class AdminResource implements AdminRESTInterface {
@Inject
SubdomainSequenceRepository subdomainSequenceRepository;
+
@Inject
- SubdomainRepository subdomainRepository;
+ DBRoller dbRoller;
+
+ private static final String NET = System.getenv("NET");;
- public Response getCounters(String auth_header) {
+ public Response getCounters() {
Map counters = subdomainSequenceRepository.getSubdomainCounters();
if (counters.isEmpty()) {
ErrorResponse.ErrorMessage errorMessage = new ErrorResponse.ErrorMessage("admin.getCounters","No subdomains in database");
@@ -32,20 +39,34 @@ public Response getCounters(String auth_header) {
return Response.ok().entity(counters).build();
}
- public Response setCounter(String auth_header, String subdomain, int value) {
- SubdomainEntity subdomainEntity = subdomainRepository.findByName(subdomain);
- if (subdomainEntity == null) {
- ErrorResponse.ErrorMessage errorMessage = new ErrorResponse.ErrorMessage("admin.setCounter","ID subdomain " + subdomain +" not found");
- ErrorResponse errorResponse = new ErrorResponse(errorMessage);
- return Response.status(Response.Status.BAD_REQUEST).entity(errorResponse).build();
+ /**
+ * rolls down the status of Mati counters for the curation application
+ * @param auth_header with authorization
+ * @return a success/failure HTTP response
+ */
+ @Transactional
+ public Response rolldown_for_curation(String auth_header) {
+ if (NET.equals("alpha")) {
+ return Response.ok().build();
}
- boolean isDone = subdomainSequenceRepository.setSubdomainCounter(subdomainEntity, value);
- if (isDone) {
+ List subdomains = List.of("disease_annotation");
+ return rolldown(subdomains);
+ }
+
+ /**
+ * rolls down the status of Mati counters from one environment to another
+ * prod -> beta
+ * beta -> alpha
+ * @param subdomains the list of subdomains to roll down
+ * @return a success/failure HTTP response
+ */
+ private Response rolldown(List subdomains) {
+ Map counters = subdomainSequenceRepository.getSubdomainCounters();
+ if (dbRoller.setSubdomainCounters(subdomains, counters)) {
return Response.ok().build();
}
else {
- return Response.notModified("Failure changing the value").build();
+ return Response.notModified("Failure changing the values").build();
}
}
-
}
diff --git a/src/main/java/org/alliancegenome/mati/interfaces/AdminRESTInterface.java b/src/main/java/org/alliancegenome/mati/interfaces/AdminRESTInterface.java
index f51a5e9..ef98ad9 100644
--- a/src/main/java/org/alliancegenome/mati/interfaces/AdminRESTInterface.java
+++ b/src/main/java/org/alliancegenome/mati/interfaces/AdminRESTInterface.java
@@ -13,40 +13,28 @@
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Tag(name = "Admin", description = "Administrative tasks")
-@Authenticated
public interface AdminRESTInterface {
/**
* Gets the counters for all the subdomains
*
- * @param auth_header Authorization Header
* @return an HTTP response
*/
@Operation(summary = "Get Counter Values")
@Path("/counters")
@GET
- Response getCounters(@NotNull @HeaderParam("Authorization") String auth_header);
-
+ Response getCounters();
/**
- * Sets the counters for a subdomain
- *
+ * Rolls down the counters to another environment
+ * prod to beta, beta to alpha
* @param auth_header Authorization Header
- * @param subdomain the subdomain to change
- * @param value the value to assign
* @return an HTTP response
*/
- @Operation(summary = "Set Counter Value")
- @Path("/counter")
- @PUT
- Response setCounter(
- @NotNull(message = "Header does not have Authorization") @HeaderParam("Authorization")
- String auth_header,
-
- @NotNull(message = "Header does not have subdomain") @HeaderParam("subdomain")
- String subdomain,
-
- @NotNull(message = "Header does not have increment value") @HeaderParam("value")
- int value
- );
+ @Operation(summary = "Roll down")
+ @Path("/rolldown_for_curation")
+ @POST
+ @Authenticated
+ Response rolldown_for_curation(
+ @NotNull(message = "Header does not have Authorization") @HeaderParam("Authorization") String auth_header);
}
diff --git a/src/main/java/org/alliancegenome/mati/repository/SubdomainSequenceRepository.java b/src/main/java/org/alliancegenome/mati/repository/SubdomainSequenceRepository.java
index 4dfed55..986c310 100644
--- a/src/main/java/org/alliancegenome/mati/repository/SubdomainSequenceRepository.java
+++ b/src/main/java/org/alliancegenome/mati/repository/SubdomainSequenceRepository.java
@@ -1,5 +1,6 @@
package org.alliancegenome.mati.repository;
+import io.quarkus.hibernate.orm.PersistenceUnit;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
diff --git a/src/main/java/org/alliancegenome/mati/rolldownrepository/DBRoller.java b/src/main/java/org/alliancegenome/mati/rolldownrepository/DBRoller.java
new file mode 100644
index 0000000..30876dc
--- /dev/null
+++ b/src/main/java/org/alliancegenome/mati/rolldownrepository/DBRoller.java
@@ -0,0 +1,68 @@
+package org.alliancegenome.mati.rolldownrepository;
+
+import io.quarkus.hibernate.orm.PersistenceUnit;
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.persistence.EntityManager;
+import jakarta.persistence.Query;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Rolls-down the MaTI database from one environment to other
+ * prod -> beta
+ * beta -> alpha
+ */
+@RequestScoped
+public class DBRoller {
+
+ @PersistenceUnit("rolldown")
+ @Inject
+ EntityManager entityManager;
+
+ /**
+ * Creates the SQL sentences for setting the PostgreSQL sequences values
+ * @param subdomains the list of subdomains
+ * @param counters a dictionary mapping subdomains to values (e.g. subdomain_person -> 120 )
+ * @return a list of SQL statements. For example:
+ * [ SETVAL('subdomain_name1_seq',10) ... SETVAL('subdomain_nameN_seq',N) ]
+ */
+ private List prepareSETVALStatements(List subdomains, Map counters) {
+ List setVALStatements = new ArrayList<>();
+ for (String subdomain : subdomains) {
+ if (counters.containsKey(subdomain)) {
+ Long counter = counters.get(subdomain);
+ if (counter > 0) {
+ setVALStatements.add("SETVAL('subdomain_" + subdomain + "_seq'," + counter + ")");
+ }
+ }
+ }
+ return setVALStatements;
+ }
+
+ /**
+ * Rolls down the values from one environment to other
+ * @param subdomains the list of subdomains
+ * @param counters a dictionary mapping subdomains to values (e.g. subdomain_reference -> 20 )
+ * @return a success/failure value
+ */
+ public boolean setSubdomainCounters(List subdomains, Map counters) {
+ List setStatements = prepareSETVALStatements(subdomains, counters);
+ if (!setStatements.isEmpty()) {
+ String body = String.join(",", setStatements);
+ String sql = "SELECT " + body;
+ Query query = entityManager.createNativeQuery(sql);
+ try {
+ int num_queries = query.getResultList().size();
+ if (num_queries == setStatements.size()) {
+ return true;
+ }
+ } catch (Exception e) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 46f8203..2d4c52c 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -10,7 +10,7 @@ okta:
client:
id: ""
secret: ""
- scopes: admin
+ scopes: ""
quarkus:
http:
@@ -20,17 +20,25 @@ quarkus:
access-control-max-age: -1
headers: "*"
datasource:
+ db-kind: postgresql
jdbc:
driver: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/mati
- username: postgres
- password: postgres
+ rolldown:
+ db-kind: postgresql
+ jdbc:
+ url: jdbc:postgresql://localhost:5432/roll
flyway:
migrate-at-start: true
hibernate-orm:
dialect: org.hibernate.dialect.PostgreSQLDialect
database:
generation: none
+ packages: ['org.alliancegenome.mati.entity','org.alliancegenome.mati.repository','io.quarkus.hibernate.orm.panache']
+ rolldown:
+ packages: ['org.alliancegenome.mati.rolldownrepository']
+ datasource: rolldown
+ validate-in-dev-mode: false
swagger-ui:
always-include: true
smallrye-openapi.management.enabled: false
@@ -48,5 +56,8 @@ quarkus:
"%test":
quarkus.datasource.jdbc:
- driver: org.testcontainers.jdbc.ContainerDatabaseDriver
- url: jdbc:tc:postgresql:13:///mati
+ driver: org.testcontainers.jdbc.ContainerDatabaseDriver
+ url: jdbc:tc:postgresql:13:///mati
+ quarkus.datasource.rolldown.jdbc:
+ driver: org.testcontainers.jdbc.ContainerDatabaseDriver
+ url: jdbc:tc:postgresql:13:///roll
diff --git a/src/test/java/org/alliancegenome/mati/controller/AdminResourceITCase.java b/src/test/java/org/alliancegenome/mati/controller/AdminResourceITCase.java
index b970b31..57db2ba 100644
--- a/src/test/java/org/alliancegenome/mati/controller/AdminResourceITCase.java
+++ b/src/test/java/org/alliancegenome/mati/controller/AdminResourceITCase.java
@@ -10,57 +10,31 @@
import static io.restassured.RestAssured.given;
import static io.restassured.http.ContentType.JSON;
+/**
+ * Tests the /api/admin/counters endpoint
+ * It runs *after* the IdentifierResourceITcase tests
+ * that mint some identifiers
+ */
@QuarkusIntegrationTest
@QuarkusTestResource(PostgresResource.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@Order(3)
public class AdminResourceITCase {
- private String authorization;
- @BeforeAll
- void setup() {
- authorization = "Bearer: " + OktaHelper.fetchOktaToken();
- }
-
- @Test
- public void setCounterDA() {
- setCounterandCheckStatus("disease_annotation", 2);
- }
-
- @Test
- public void setCounterPerson() {
- setCounterandCheckStatus("person", 4);
- }
-
- @Test
- public void setCounterResource() {
- setCounterandCheckStatus("resource", 8);
- }
@Test
public void getCounters() {
Map counters = given().
- contentType(JSON).
- header("Accept", "application/json").
- header("Authorization", authorization).
- when().
- get("http://localhost:8081/api/admin/counters").
- then().
- statusCode(200)
- .extract().body().as(Map.class);
-
- Assertions.assertEquals(counters.get("disease_annotation"), 2);
+ contentType(JSON).
+ header("Accept", "application/json").
+ when().
+ get("http://localhost:8081/api/admin/counters").
+ then().
+ statusCode(200)
+ .extract().body().as(Map.class);
+
+ Assertions.assertEquals(counters.get("disease_annotation"), 5);
Assertions.assertEquals(counters.get("person"), 4);
- Assertions.assertEquals(counters.get("resource"), 8);
- }
-
- private void setCounterandCheckStatus(String subdomain, int value) {
- given().
- contentType(JSON).
- header("Authorization", authorization).
- header("subdomain", subdomain).
- header("value", value).
- when().
- put("http://localhost:8081/api/admin/counter").
- then().
- statusCode(200);
+ Assertions.assertEquals(counters.get("resource"), 6);
+ Assertions.assertEquals(counters.get("reference"), 3);
}
}
diff --git a/src/test/java/org/alliancegenome/mati/controller/IdentifierResourceITCase.java b/src/test/java/org/alliancegenome/mati/controller/IdentifierResourceITCase.java
index d82f499..4a10390 100644
--- a/src/test/java/org/alliancegenome/mati/controller/IdentifierResourceITCase.java
+++ b/src/test/java/org/alliancegenome/mati/controller/IdentifierResourceITCase.java
@@ -6,16 +6,18 @@
import org.alliancegenome.mati.configuration.PostgresResource;
import org.alliancegenome.mati.entity.IdentifiersRange;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.*;
import static io.restassured.RestAssured.given;
+/**
+ * Tests the /api/identifier (PUT, POST) endpoints
+ * for minting identifiers
+ */
@QuarkusIntegrationTest
@QuarkusTestResource(PostgresResource.class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+@Order(2)
class IdentifierResourceITCase {
private String authorization;
diff --git a/src/test/java/org/alliancegenome/mati/controller/SubdomainResourceITCase.java b/src/test/java/org/alliancegenome/mati/controller/SubdomainResourceITCase.java
index 7bf576d..570daff 100644
--- a/src/test/java/org/alliancegenome/mati/controller/SubdomainResourceITCase.java
+++ b/src/test/java/org/alliancegenome/mati/controller/SubdomainResourceITCase.java
@@ -9,6 +9,7 @@
import org.alliancegenome.mati.entity.SubdomainEntity;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import java.util.List;
@@ -18,6 +19,7 @@
@QuarkusIntegrationTest
@QuarkusTestResource(PostgresResource.class)
+@Order(1)
class SubdomainResourceITCase {
@BeforeEach
diff --git a/src/test/resources/junit-platform.properties b/src/test/resources/junit-platform.properties
new file mode 100644
index 0000000..be47bad
--- /dev/null
+++ b/src/test/resources/junit-platform.properties
@@ -0,0 +1,2 @@
+junit.jupiter.testclass.order.default = \
+ org.junit.jupiter.api.ClassOrderer$OrderAnnotation