Skip to content

Commit

Permalink
Remove code used for stashing - add supervision classes to handle exi…
Browse files Browse the repository at this point in the history
…sting stashed elements deletion (#84)

Signed-off-by: LE SAULNIER Kevin <[email protected]>
  • Loading branch information
klesaulnier authored Apr 22, 2024
1 parent 6f16462 commit 3cbc513
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -242,13 +242,13 @@ public ResponseEntity<Void> deleteElement(@PathVariable("elementUuid") UUID elem
return ResponseEntity.ok().build();
}

@DeleteMapping(value = "/explore/elements/{directoryUuid}/delete-stashed")
@DeleteMapping(value = "/explore/elements/{directoryUuid}", params = "ids")
@Operation(summary = "Remove directories/elements")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "directories/elements was successfully removed")})
public ResponseEntity<Void> deleteElements(@RequestParam("ids") List<UUID> elementsUuid,
@RequestHeader("userId") String userId,
@PathVariable String directoryUuid) {
exploreService.deleteElements(elementsUuid, userId);
@PathVariable UUID directoryUuid) {
exploreService.deleteElementsFromDirectory(elementsUuid, directoryUuid, userId);
return ResponseEntity.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.gridsuite.explore.server;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.gridsuite.explore.server.services.SupervisionService;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.UUID;

@RestController
@RequestMapping(value = "/" + ExploreApi.API_VERSION + "/supervision")
@Tag(name = "explore-server - Supervision")
public class SupervisionController {
private final SupervisionService supervisionService;

public SupervisionController(SupervisionService supervisionService) {
this.supervisionService = supervisionService;
}

@DeleteMapping(value = "/explore/elements", params = "ids")
@Operation(summary = "Remove directories/elements")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "directories/elements was successfully removed")})
public ResponseEntity<Void> deleteElements(@RequestParam("ids") List<UUID> elementsUuid,
@RequestHeader("userId") String userId) {
supervisionService.deleteElements(elementsUuid, userId);
return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,12 @@ public void deleteDirectoryElement(UUID elementUuid, String userId) {
restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class);
}

public void deleteDirectoryElements(List<UUID> elementUuids, String userId) {
public void deleteElementsFromDirectory(List<UUID> elementUuids, UUID parentDirectoryUuid, String userId) {
var ids = elementUuids.stream().map(UUID::toString).collect(Collectors.joining(","));
String path = UriComponentsBuilder
.fromPath(ELEMENTS_SERVER_ROOT_PATH + "?ids=" + ids)
.fromPath(ELEMENTS_SERVER_ROOT_PATH)
.queryParam("ids", ids)
.queryParam("parentDirectoryUuid", parentDirectoryUuid)
.buildAndExpand()
.toUriString();
HttpHeaders headers = new HttpHeaders();
Expand Down Expand Up @@ -149,7 +151,6 @@ public void notifyDirectoryChanged(UUID elementUuid, String userId) {

private List<ElementAttributes> getDirectoryElements(UUID directoryUuid, String userId) {
String path = UriComponentsBuilder.fromPath(DIRECTORIES_SERVER_ROOT_PATH + "/{directoryUuid}/elements")
.queryParam("stashed", true)
.buildAndExpand(directoryUuid)
.toUriString();
HttpHeaders headers = new HttpHeaders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ public void deleteElement(UUID id, String userId) {
}
}

public void deleteElements(List<UUID> uuids, String userId) {
public void deleteElementsFromDirectory(List<UUID> uuids, UUID parentDirectoryUuids, String userId) {
try {
uuids.forEach(id -> directoryService.deleteElement(id, userId));
// FIXME dirty fix to ignore errors and still delete the elements in the directory-server. To delete when handled properly.
} catch (Exception e) {
LOGGER.error(e.toString(), e);
} finally {
directoryService.deleteDirectoryElements(uuids, userId);
directoryService.deleteElementsFromDirectory(uuids, parentDirectoryUuids, userId);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* Copyright (c) 2024, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.gridsuite.explore.server.services;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
* @author Kevin Le Saulnier <kevin.lesaulnier at rte-france.com>
*/
@Service
public class SupervisionService {
private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionService.class);
private final DirectoryService directoryService;
private final String directoryServerBaseUri;
private final RestTemplate restTemplate;

private static final String DIRECTORY_SERVER_API_VERSION = "v1";
private static final String DELIMITER = "/";
private static final String SUPERVISION_PATH = DELIMITER + "supervision";
private static final String ELEMENTS_SERVER_ROOT_PATH = DELIMITER + DIRECTORY_SERVER_API_VERSION + DELIMITER + SUPERVISION_PATH + DELIMITER
+ "elements";

public SupervisionService(DirectoryService directoryService, RestTemplate restTemplate, RemoteServicesProperties remoteServicesProperties) {
this.directoryServerBaseUri = remoteServicesProperties.getServiceUri("directory-server");
this.directoryService = directoryService;
this.restTemplate = restTemplate;
}

public void deleteElements(List<UUID> uuids, String userId) {
uuids.forEach(id -> {
try {
directoryService.deleteElement(id, userId);
} catch (Exception e) {
// if deletion fails (element does not exist, server is down...), the process keeps proceeding to at least delete references in directory-server
// orphan elements will be deleted in a dedicated script
LOGGER.error(e.toString(), e);
}
});
deleteDirectoryElements(uuids);
}

// DOES NOT CHECK OWNER BEFORE DELETING
private void deleteDirectoryElements(List<UUID> elementUuids) {
var ids = elementUuids.stream().map(UUID::toString).collect(Collectors.joining(","));
String path = UriComponentsBuilder
.fromPath(ELEMENTS_SERVER_ROOT_PATH)
.queryParam("ids", ids)
.buildAndExpand()
.toUriString();
HttpHeaders headers = new HttpHeaders();
restTemplate.exchange(directoryServerBaseUri + path, HttpMethod.DELETE, new HttpEntity<>(headers), Void.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -465,7 +465,7 @@ public void deleteElement(UUID elementUUid) throws Exception {

public void deleteElements(List<UUID> elementUuids, UUID parentUuid) throws Exception {
var ids = elementUuids.stream().map(UUID::toString).collect(Collectors.joining(","));
mockMvc.perform(delete("/v1/explore/elements/{parentUuid}/delete-stashed?ids=" + ids, parentUuid)
mockMvc.perform(delete("/v1/explore/elements/{parentUuid}?ids=" + ids, parentUuid)
.header("userId", USER1))
.andExpect(status().isOk());
}
Expand Down
69 changes: 69 additions & 0 deletions src/test/java/org/gridsuite/explore/server/SupervisionTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package org.gridsuite.explore.server;

import org.gridsuite.explore.server.dto.ElementAttributes;
import org.gridsuite.explore.server.services.DirectoryService;
import org.gridsuite.explore.server.services.SupervisionService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.UUID;

import static org.mockito.Mockito.*;

/**
* @author Kevin Le Saulnier <kevin.lesaulnier at rte-france.com>
*/
@SpringBootTest
class SupervisionTest {
@Autowired
SupervisionService supervisionService;

@MockBean
DirectoryService directoryService;

@MockBean
RestTemplate restTemplate;

ElementAttributes filter = new ElementAttributes(UUID.randomUUID(), "filter", "FILTER", null, "userId", 0L, null, null);

ElementAttributes study = new ElementAttributes(UUID.randomUUID(), "study", "STUDY", null, "userId", 0L, null, null);

@Test
void testDeleteElements() {
List<UUID> uuidsToDelete = List.of(filter.getElementUuid(), study.getElementUuid());
supervisionService.deleteElements(uuidsToDelete, "userId");
// deletions of both elements with foreach towards respective microservice
verify(directoryService, times(1)).deleteElement(filter.getElementUuid(), "userId");
verify(directoryService, times(1)).deleteElement(study.getElementUuid(), "userId");
// deletions of both elements in directory server
verify(restTemplate, times(1)).exchange(matches(".*/supervision/.*"), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
}

@Test
void testDeleteElementsWithErrors() {
List<UUID> uuidsToDelete = List.of(filter.getElementUuid(), study.getElementUuid());

// one deletion will fail, this test checks deletions does not stop even when one of them is throwing an exception
doThrow(new RuntimeException("An error occured when deleting filter")).when(directoryService).deleteElement(filter.getElementUuid(), "userId");

supervisionService.deleteElements(uuidsToDelete, "userId");
// deletions of both elements with foreach towards respective microservice
verify(directoryService, times(1)).deleteElement(filter.getElementUuid(), "userId");
verify(directoryService, times(1)).deleteElement(study.getElementUuid(), "userId");
// deletions of both elements in directory server
verify(restTemplate, times(1)).exchange(matches(".*/supervision/.*"), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class));
}

@AfterEach
public void verifyNoMoreInteractionsMocks() {
verifyNoMoreInteractions(restTemplate);
verifyNoMoreInteractions(directoryService);
}
}

0 comments on commit 3cbc513

Please sign in to comment.