Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

disable auto case indexation #39

Merged
merged 23 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 17 additions & 12 deletions src/main/java/com/powsybl/caseserver/CaseController.java
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,10 @@ public ResponseEntity<Boolean> exists(@PathVariable("caseUuid") UUID caseUuid) {
@Operation(summary = "import a case")
@SuppressWarnings("javasecurity:S5145")
public ResponseEntity<UUID> importCase(@RequestParam("file") MultipartFile file,
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration) {
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration,
@RequestParam(value = "indexed", required = false, defaultValue = "false") boolean indexed) {
LOGGER.debug("importCase request received with file = {}", file.getName());
UUID caseUuid = caseService.importCase(file, withExpiration);
UUID caseUuid = caseService.importCase(file, withExpiration, indexed);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename by withIndexation
But in database leave indexed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return ResponseEntity.ok().body(caseUuid);
}

Expand All @@ -165,9 +166,10 @@ public ResponseEntity<UUID> importCase(@RequestParam("file") MultipartFile file,
@ApiResponse(responseCode = "500", description = "An error occurred during the case file duplication")})
public ResponseEntity<UUID> duplicateCase(
@RequestParam("duplicateFrom") UUID caseId,
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration) {
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove paramter
Do indexation if the origin case is indexed only

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@RequestParam(value = "indexed", required = false, defaultValue = "false") boolean indexed) {
LOGGER.debug("duplicateCase request received with parameter sourceCaseUuid = {}", caseId);
UUID newCaseUuid = caseService.duplicateCase(caseId, withExpiration);
UUID newCaseUuid = caseService.duplicateCase(caseId, withExpiration, indexed);
return ResponseEntity.ok().body(newCaseUuid);
}

Expand All @@ -182,6 +184,17 @@ public ResponseEntity<Void> disableCaseExpiration(@PathVariable("caseUuid") UUID
return ResponseEntity.ok().build();
}

@PutMapping(value = "/cases/{caseUuid}/indexation")
jamal-khey marked this conversation as resolved.
Show resolved Hide resolved
@Operation(summary = "enable automatic indexation of the case")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "The case index has been changed"),
@ApiResponse(responseCode = "404", description = "Source case not found")})
public ResponseEntity<Void> enableCaseIndexation(@PathVariable("caseUuid") UUID caseUuid, @RequestParam("indexed") boolean indexed) {
LOGGER.debug("enableIndexation request received for caseUuid = {}", caseUuid);
caseService.enableCaseIndexation(caseUuid, indexed);
return ResponseEntity.ok().build();
}

@DeleteMapping(value = "/cases/{caseUuid}")
@Operation(summary = "delete a case")
public ResponseEntity<Void> deleteCase(@PathVariable("caseUuid") UUID caseUuid) {
Expand All @@ -206,14 +219,6 @@ public ResponseEntity<List<CaseInfos>> searchCases(@RequestParam(value = "q") St
return ResponseEntity.ok().body(cases);
}

@PostMapping(value = "/cases/reindex-all")
@Operation(summary = "reindex all cases")
public ResponseEntity<Void> reindexAllCases() {
LOGGER.debug("reindex all cases request received");
caseService.reindexAllCases();
return ResponseEntity.ok().build();
}

@GetMapping(value = "/cases/metadata")
@Operation(summary = "Get cases Metadata")
public ResponseEntity<List<CaseInfos>> getMetadata(@RequestParam("ids") List<UUID> ids) {
Expand Down
53 changes: 33 additions & 20 deletions src/main/java/com/powsybl/caseserver/CaseService.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import com.powsybl.caseserver.dto.CaseInfos;
import com.powsybl.caseserver.dto.ExportCaseInfos;
import com.powsybl.caseserver.elasticsearch.CaseInfosRepository;
import com.powsybl.caseserver.elasticsearch.CaseInfosService;
import com.powsybl.caseserver.parsers.FileNameInfos;
import com.powsybl.caseserver.parsers.FileNameParser;
Expand Down Expand Up @@ -46,14 +47,7 @@
import java.nio.file.StandardCopyOption;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Properties;
import java.util.UUID;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.zip.ZipEntry;
Expand Down Expand Up @@ -89,6 +83,8 @@ public class CaseService {

@Value("${case-store-directory:#{systemProperties['user.home'].concat(\"/cases\")}}")
private String rootDirectory;
@Autowired
private CaseInfosRepository caseInfosRepository;

public CaseService(CaseMetadataRepository caseMetadataRepository) {
this.caseMetadataRepository = caseMetadataRepository;
Expand Down Expand Up @@ -179,7 +175,7 @@ boolean caseExists(UUID caseName) {
return Files.exists(caseFile) && Files.isRegularFile(caseFile);
}

UUID importCase(MultipartFile mpf, boolean withExpiration) {
UUID importCase(MultipartFile mpf, boolean withExpiration, boolean indexed) {
checkStorageInitialization();

UUID caseUuid = UUID.randomUUID();
Expand Down Expand Up @@ -214,14 +210,16 @@ UUID importCase(MultipartFile mpf, boolean withExpiration) {
throw e;
}

createCaseMetadataEntity(caseUuid, withExpiration);
createCaseMetadataEntity(caseUuid, withExpiration, indexed);
CaseInfos caseInfos = createInfos(caseFile.getFileName().toString(), caseUuid, importer.getFormat());
caseInfosService.addCaseInfos(caseInfos);
if (indexed) {
caseInfosService.addCaseInfos(caseInfos);
}
sendImportMessage(caseInfos.createMessage());
return caseUuid;
}

UUID duplicateCase(UUID sourceCaseUuid, boolean withExpiration) {
UUID duplicateCase(UUID sourceCaseUuid, boolean withExpiration, boolean indexed) {
try {
Path existingCaseFile = getCaseFile(sourceCaseUuid);
if (existingCaseFile == null || existingCaseFile.getParent() == null) {
Expand All @@ -237,8 +235,10 @@ UUID duplicateCase(UUID sourceCaseUuid, boolean withExpiration) {

CaseInfos existingCaseInfos = caseInfosService.getCaseInfosByUuid(sourceCaseUuid.toString()).orElseThrow();
CaseInfos caseInfos = createInfos(existingCaseInfos.getName(), newCaseUuid, existingCaseInfos.getFormat());
caseInfosService.addCaseInfos(caseInfos);
createCaseMetadataEntity(newCaseUuid, withExpiration);
if (indexed) {
caseInfosService.addCaseInfos(caseInfos);
}
createCaseMetadataEntity(newCaseUuid, withExpiration, indexed);

sendImportMessage(caseInfos.createMessage());
return newCaseUuid;
Expand All @@ -248,12 +248,23 @@ UUID duplicateCase(UUID sourceCaseUuid, boolean withExpiration) {
}
}

private void createCaseMetadataEntity(UUID newCaseUuid, boolean withExpiration) {
private void createCaseMetadataEntity(UUID newCaseUuid, boolean withExpiration, boolean indexed) {
Instant expirationTime = null;
if (withExpiration) {
expirationTime = Instant.now().plus(1, ChronoUnit.HOURS);
}
caseMetadataRepository.save(new CaseMetadataEntity(newCaseUuid, expirationTime));
caseMetadataRepository.save(new CaseMetadataEntity(newCaseUuid, expirationTime, indexed));
}

public Set<UUID> getCaseToReindex() {
return caseMetadataRepository.findAllByIndexedTrue()
.stream()
.map(CaseMetadataEntity::getId)
.collect(Collectors.toSet());
}

public List<CaseInfos> getAllCases() {
return getCases(getStorageRootDir());
}

CaseInfos createInfos(String fileBaseName, UUID caseUuid, String format) {
Expand All @@ -273,6 +284,12 @@ public void disableCaseExpiration(UUID caseUuid) {
caseMetadataEntity.setExpirationDate(null);
}

@Transactional
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

public void enableCaseIndexation(UUID caseUuid, boolean indexed) {
CaseMetadataEntity caseMetadataEntity = caseMetadataRepository.findById(caseUuid).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "case " + caseUuid + " not found"));
caseMetadataEntity.setIndexed(indexed);
}

Optional<Network> loadNetwork(UUID caseUuid) {
checkStorageInitialization();

Expand Down Expand Up @@ -373,10 +390,6 @@ private void sendImportMessage(Message<String> message) {
caseInfosPublisher.send("publishCaseImport-out-0", message);
}

public void reindexAllCases() {
caseInfosService.recreateAllCaseInfos(getCases(getStorageRootDir()));
}

public List<CaseInfos> getMetadata(List<UUID> ids) {
List<CaseInfos> cases = new ArrayList<>();
ids.forEach(caseUuid -> {
Expand Down
80 changes: 80 additions & 0 deletions src/main/java/com/powsybl/caseserver/SupervisionController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* 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 com.powsybl.caseserver;

import com.powsybl.caseserver.elasticsearch.CaseInfosService;
import com.powsybl.caseserver.services.SupervisionService;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

/**
* @author Jamal KHEYYAD <jamal.kheyyad at rte-international.com>
*/
@RestController
@RequestMapping(value = "/" + CaseConstants.API_VERSION + "/supervision")
@Tag(name = "case-server - Supervision")
public class SupervisionController {
private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionController.class);

private final SupervisionService supervisionService;
private final ClientConfiguration elasticsearchClientConfiguration;
private final CaseInfosService caseInfosService;

public SupervisionController(SupervisionService supervisionService, ClientConfiguration elasticsearchClientConfiguration, CaseInfosService caseInfosService) {
this.supervisionService = supervisionService;
this.elasticsearchClientConfiguration = elasticsearchClientConfiguration;
this.caseInfosService = caseInfosService;
}

@GetMapping(value = "/elasticsearch-host")
@Operation(summary = "get the elasticsearch address")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "the elasticsearch address")})
public ResponseEntity<String> getElasticsearchHost() {
String host = elasticsearchClientConfiguration.getEndpoints().get(0).getHostName()
+ ":"
+ elasticsearchClientConfiguration.getEndpoints().get(0).getPort();
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(host);
}

@GetMapping(value = "/cases/index-name")
@Operation(summary = "get the indexed directory elements index name")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Indexed directory elements index name")})
public ResponseEntity<String> getIndexedDirectoryElementsIndexName() {
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(caseInfosService.getDirectoryElementsIndexName());
}

@PostMapping(value = "/cases/reindex")
@Operation(summary = "reindex all cases")
public ResponseEntity<Void> reindexAllCases() {
LOGGER.debug("reindex all cases request received");
supervisionService.reindexAllCases();
return ResponseEntity.ok().build();
}

@DeleteMapping(value = "/cases/indexation")
@Operation(summary = "delete indexed elements")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "all indexed elements have been deleted")})
public ResponseEntity<String> deleteIndexedDirectoryElements() {
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(Long.toString(supervisionService.deleteIndexedDirectoryElements()));
}

@GetMapping(value = "/cases/indexation-count")
@Operation(summary = "get indexed cases count")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Indexed cases count")})
public ResponseEntity<String> getIndexedDirectoryElementsCount() {
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(Long.toString(supervisionService.getIndexedCaseElementsCount()));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import co.elastic.clients.elasticsearch._types.query_dsl.QueryStringQuery;
import com.google.common.collect.Lists;
import com.powsybl.caseserver.dto.CaseInfos;
import lombok.Getter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand Down Expand Up @@ -42,6 +44,10 @@ public class CaseInfosService {
@Autowired
private ElasticsearchOperations operations;

@Value(ESConfig.CASE_INFOS_INDEX_NAME)
@Getter
private String directoryElementsIndexName;

public CaseInfos addCaseInfos(@NonNull final CaseInfos ci) {
caseInfosRepository.save(ci);
return ci;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
@EnableElasticsearchRepositories
public class ESConfig extends ElasticsearchConfiguration {

public static final String CASE_INFOS_INDEX_NAME = "#{@environment.getProperty('powsybl-ws.elasticsearch.index.prefix')}cases";

@Value("#{'${spring.data.elasticsearch.embedded:false}' ? 'localhost' : '${spring.data.elasticsearch.host}'}")
private String esHost;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,7 @@ public class CaseMetadataEntity {

@Column(name = "expirationDate", columnDefinition = "timestamptz")
private Instant expirationDate;

@Column(name = "indexed", columnDefinition = "boolean default false", nullable = false)
private boolean indexed = false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

/**
Expand All @@ -17,4 +18,8 @@
@Repository
public interface CaseMetadataRepository extends JpaRepository<CaseMetadataEntity, UUID> {

@Override
List<CaseMetadataEntity> findAllById(Iterable<UUID> uuids);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


List<CaseMetadataEntity> findAllByIndexedTrue();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* 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 com.powsybl.caseserver.services;

import com.powsybl.caseserver.CaseService;
import com.powsybl.caseserver.dto.CaseInfos;
import com.powsybl.caseserver.elasticsearch.CaseInfosRepository;
import com.powsybl.caseserver.elasticsearch.CaseInfosService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author Jamal KHEYYAD <jamal.kheyyad at rte-international.com>
*/
@Service
public class SupervisionService {
private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionService.class);

private final CaseInfosService caseInfosService;
private final CaseService caseService;
private final CaseInfosRepository caseInfosRepository;

public SupervisionService(CaseInfosService caseInfosService, CaseService caseService, CaseInfosRepository caseInfosRepository) {
this.caseInfosService = caseInfosService;
this.caseService = caseService;
this.caseInfosRepository = caseInfosRepository;
}

public void reindexAllCases() {
List<CaseInfos> allCases = caseService.getAllCases();
Set<UUID> casesToIndex = caseService.getCaseToReindex();
List<CaseInfos> data = allCases.stream().filter(c -> casesToIndex.contains(c.getUuid())).toList();
caseInfosService.recreateAllCaseInfos(data);
}

public long deleteIndexedDirectoryElements() {
AtomicReference<Long> startTime = new AtomicReference<>();
startTime.set(System.nanoTime());

long nbIndexesToDelete = getIndexedCaseElementsCount();
caseInfosRepository.deleteAll();
LOGGER.trace("Indexed directory elements deletion : {} seconds", TimeUnit.NANOSECONDS.toSeconds(System.nanoTime() - startTime.get()));
return nbIndexesToDelete;
}

public long getIndexedCaseElementsCount() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove elements -> getIndexedCasesCount

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

return caseInfosRepository.count();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet author="jamalk (generated)" id="1722005243703-1">
<addColumn tableName="case_metadata">
<column defaultValueBoolean="false" name="indexed" type="boolean">
<constraints nullable="false"/>
</column>
</addColumn>
</changeSet>
</databaseChangeLog>
Loading
Loading