From db1bf1385f744f9064965ecf4442bcb0f8ab3487 Mon Sep 17 00:00:00 2001 From: Andrea Lamparelli Date: Tue, 19 Nov 2024 10:10:57 +0100 Subject: [PATCH] Revert upload run return type to string Signed-off-by: Andrea Lamparelli --- docs/site/content/en/openapi/openapi.yaml | 19 +++--------- .../horreum/api/services/RunService.java | 8 ++--- .../tools/horreum/svc/RunServiceImpl.java | 2 +- .../tools/horreum/svc/ServiceMediator.java | 1 - .../tools/horreum/svc/BaseServiceTest.java | 31 ++++++++++++------- .../tools/horreum/api/client/RunService.java | 2 +- .../tools/horreum/it/HorreumClientIT.java | 3 +- 7 files changed, 32 insertions(+), 34 deletions(-) diff --git a/docs/site/content/en/openapi/openapi.yaml b/docs/site/content/en/openapi/openapi.yaml index 632b49fde..3ef780893 100644 --- a/docs/site/content/en/openapi/openapi.yaml +++ b/docs/site/content/en/openapi/openapi.yaml @@ -653,20 +653,11 @@ paths: \ of created run IDs if available, or an empty list if processing is still\ \ ongoing. Label values and change detection processing is performed asynchronously." content: - application/json: + text/plain: schema: - type: array - items: - format: int32 - type: integer - example: - - 101 - - 102 - - 103 - example: - - 101 - - 102 - - 103 + type: string + example: "101,102,103" + example: "101,102,103" "204": description: Data is valid but no run was created content: @@ -674,7 +665,7 @@ paths: "400": description: Some fields are missing or invalid content: - application/json: {} + text/plain: {} /api/run/list: get: tags: diff --git a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java index 66a77a920..12953141a 100644 --- a/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java +++ b/horreum-api/src/main/java/io/hyperfoil/tools/horreum/api/services/RunService.java @@ -225,9 +225,9 @@ Response add(@QueryParam("test") String testNameOrId, @APIResponses(value = { @APIResponse(responseCode = "202", description = "The request has been accepted for processing. Returns a list of created run IDs if available, " + "or an empty list if processing is still ongoing. Label values and change detection processing " + - "is performed asynchronously.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.ARRAY, implementation = Integer.class, example = "[101, 102, 103]"), example = "[101, 102, 103]")), + "is performed asynchronously.", content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = SchemaType.STRING, example = "101,102,103"), example = "101,102,103")), @APIResponse(responseCode = "204", description = "Data is valid but no run was created", content = @Content(mediaType = MediaType.TEXT_PLAIN)), - @APIResponse(responseCode = "400", description = "Some fields are missing or invalid", content = @Content(mediaType = MediaType.APPLICATION_JSON)) + @APIResponse(responseCode = "400", description = "Some fields are missing or invalid", content = @Content(mediaType = MediaType.TEXT_PLAIN)) }) Response addRunFromData(@QueryParam("start") String start, @QueryParam("stop") String stop, @@ -245,9 +245,9 @@ Response addRunFromData(@QueryParam("start") String start, @APIResponses(value = { @APIResponse(responseCode = "202", description = "The request has been accepted for processing. Returns a list of created run IDs if available, " + "or an empty list if processing is still ongoing. Label values and change detection processing " + - "is performed asynchronously.", content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(type = SchemaType.ARRAY, implementation = Integer.class, example = "[101, 102, 103]"), example = "[101, 102, 103]")), + "is performed asynchronously.", content = @Content(mediaType = MediaType.TEXT_PLAIN, schema = @Schema(type = SchemaType.STRING, example = "101,102,103"), example = "101,102,103")), @APIResponse(responseCode = "204", description = "Data is valid but no run was created", content = @Content(mediaType = MediaType.TEXT_PLAIN)), - @APIResponse(responseCode = "400", description = "Some fields are missing or invalid", content = @Content(mediaType = MediaType.APPLICATION_JSON)) + @APIResponse(responseCode = "400", description = "Some fields are missing or invalid", content = @Content(mediaType = MediaType.TEXT_PLAIN)) }) Response addRunFromData(@Parameter(required = true) @QueryParam("start") String start, @Parameter(required = true) @QueryParam("stop") String stop, diff --git a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/RunServiceImpl.java b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/RunServiceImpl.java index edefbdb8d..4d65d03e6 100644 --- a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/RunServiceImpl.java +++ b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/RunServiceImpl.java @@ -534,7 +534,7 @@ Response addRunFromData(String start, String stop, String test, // if the request is accepted return 202 with all generated run ids // if no run ids, means all run upload have been queued up (datastore scenario) return Response.status(Response.Status.ACCEPTED) - .entity(runs.stream().map(val -> val.runId).toList()) + .entity(runs.stream().map(val -> Integer.toString(val.runId)).collect(Collectors.joining(","))) .build(); } diff --git a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/ServiceMediator.java b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/ServiceMediator.java index 6c08a5cda..44e8cd5e7 100644 --- a/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/ServiceMediator.java +++ b/horreum-backend/src/main/java/io/hyperfoil/tools/horreum/svc/ServiceMediator.java @@ -198,7 +198,6 @@ public void processSchemaSync(int schemaId) { public void processRunUpload(RunUpload runUpload) { log.debugf("Run Upload: %d", runUpload.testId); runService.persistRun(runUpload); - } @Transactional(Transactional.TxType.NOT_SUPPORTED) diff --git a/horreum-backend/src/test/java/io/hyperfoil/tools/horreum/svc/BaseServiceTest.java b/horreum-backend/src/test/java/io/hyperfoil/tools/horreum/svc/BaseServiceTest.java index 6c3332ea9..4eed13c06 100644 --- a/horreum-backend/src/test/java/io/hyperfoil/tools/horreum/svc/BaseServiceTest.java +++ b/horreum-backend/src/test/java/io/hyperfoil/tools/horreum/svc/BaseServiceTest.java @@ -288,17 +288,18 @@ protected int uploadRun(long start, long stop, Object runJson, String test) { } protected int uploadRun(long start, long stop, Object runJson, String test, String owner, Access access) { - List runIds = given().auth().oauth2(getUploaderToken()) + String runIdsAsString = given().auth().oauth2(getUploaderToken()) .header(HttpHeaders.CONTENT_TYPE, "application/json") .body(runJson) .post("/api/run/data?start=" + start + "&stop=" + stop + "&test=" + test + "&owner=" + owner + "&access=" + access) .then() .statusCode(202) - .extract().as(List.class); + .extract().asString(); + List runIds = parseCommaSeparatedIds(runIdsAsString); assertEquals(1, runIds.size()); - return Integer.parseInt(runIds.get(0).toString()); + return runIds.get(0); } protected List uploadRun(String start, String stop, String test, String owner, Access access, @@ -307,17 +308,18 @@ protected List uploadRun(String start, String stop, String test, String schemaUri, description, jakarta.ws.rs.core.Response.Status.ACCEPTED.getStatusCode(), runJson); } - @SuppressWarnings("unchecked") protected List uploadRun(String start, String stop, String test, String owner, Access access, String schemaUri, String description, Integer statusCode, Object runJson) { - return RestAssured.given().auth().oauth2(getUploaderToken()) + String runIdsAsString = RestAssured.given().auth().oauth2(getUploaderToken()) .header(HttpHeaders.CONTENT_TYPE, "application/json") .body(runJson) .post("/api/run/data?start=" + start + "&stop=" + stop + "&test=" + test + "&owner=" + owner + "&access=" + access + "&schema=" + schemaUri + "&description=" + description) .then() .statusCode(statusCode) - .extract().as(List.class); + .extract().asString(); + + return parseCommaSeparatedIds(runIdsAsString); } protected int uploadRun(long timestamp, JsonNode data, JsonNode metadata, String testName) { @@ -326,8 +328,7 @@ protected int uploadRun(long timestamp, JsonNode data, JsonNode metadata, String protected int uploadRun(long start, long stop, JsonNode data, JsonNode metadata, String testName, String owner, Access access) { - @SuppressWarnings("unchecked") - List runIds = given().auth().oauth2(getUploaderToken()) + String runIdsAsString = given().auth().oauth2(getUploaderToken()) .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA) // the .toString().getBytes(...) is required because RestAssured otherwise won't send the filename // and Quarkus in turn will use null FileUpload: https://github.com/quarkusio/quarkus/issues/20938 @@ -338,15 +339,15 @@ protected int uploadRun(long start, long stop, JsonNode data, JsonNode metadata, + access) .then() .statusCode(202) - .extract().as(List.class); + .extract().asString(); + List runIds = parseCommaSeparatedIds(runIdsAsString); assertEquals(1, runIds.size()); return runIds.get(0); } protected int uploadRun(String start, String stop, JsonNode data, JsonNode metadata, String testName, String owner, Access access) { - @SuppressWarnings("unchecked") - List runIds = given().auth().oauth2(getUploaderToken()) + String runIdsAsString = given().auth().oauth2(getUploaderToken()) .header(HttpHeaders.CONTENT_TYPE, MediaType.MULTIPART_FORM_DATA) // the .toString().getBytes(...) is required because RestAssured otherwise won't send the filename // and Quarkus in turn will use null FileUpload: https://github.com/quarkusio/quarkus/issues/20938 @@ -357,7 +358,8 @@ protected int uploadRun(String start, String stop, JsonNode data, JsonNode metad + access) .then() .statusCode(202) - .extract().as(List.class); + .extract().asString(); + List runIds = parseCommaSeparatedIds(runIdsAsString); assertEquals(1, runIds.size()); return runIds.get(0); } @@ -1154,4 +1156,9 @@ protected void testSerialization(T event, Class eventClass) { throw new AssertionError("Cannot deserialize " + event + " from " + changeJson.toPrettyString(), e); } } + + private List parseCommaSeparatedIds(String idsAsString) { + return idsAsString.isBlank() ? List.of() + : Stream.of(idsAsString.trim().split(",")).map(Integer::parseInt).collect(Collectors.toList()); + } } diff --git a/horreum-client/src/main/java/io/hyperfoil/tools/horreum/api/client/RunService.java b/horreum-client/src/main/java/io/hyperfoil/tools/horreum/api/client/RunService.java index 208a7ecd3..d7f23b999 100644 --- a/horreum-client/src/main/java/io/hyperfoil/tools/horreum/api/client/RunService.java +++ b/horreum-client/src/main/java/io/hyperfoil/tools/horreum/api/client/RunService.java @@ -74,7 +74,7 @@ Response add(@QueryParam("test") String testNameOrId, @POST @Path("data") - @Produces(MediaType.TEXT_PLAIN) // run ID as string + @Produces(MediaType.TEXT_PLAIN) // array of generated Run IDs Response addRunFromData(@QueryParam("start") String start, @QueryParam("stop") String stop, @QueryParam("test") String test, diff --git a/horreum-integration-tests/src/test/java/io/hyperfoil/tools/horreum/it/HorreumClientIT.java b/horreum-integration-tests/src/test/java/io/hyperfoil/tools/horreum/it/HorreumClientIT.java index 8cc9b052b..61d9b26e3 100644 --- a/horreum-integration-tests/src/test/java/io/hyperfoil/tools/horreum/it/HorreumClientIT.java +++ b/horreum-integration-tests/src/test/java/io/hyperfoil/tools/horreum/it/HorreumClientIT.java @@ -133,7 +133,8 @@ public void testAddRunFromData() throws JsonProcessingException { JsonNode payload = new ObjectMapper().readTree(resourceToString("data/config-quickstart.jvm.json")); try { - horreumClient.runService.addRunFromData("$.start", "$.stop", dummyTest.name, dummyTest.owner, Access.PUBLIC, + horreumClient.runService.addRunFromData("$.start", "$.stop", dummyTest.name, dummyTest.owner, + Access.PUBLIC, null, "test", payload); } catch (BadRequestException badRequestException) { fail(badRequestException.getMessage()