Skip to content
Open
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
07e49bd
feat: expand filtering
Logaka Dec 2, 2025
9765ff6
refactor: rewrite dynamic SQL filter
Logaka Dec 8, 2025
e0963a5
Merge branch 'main' into feat/backupV2-add-complex-filtering
Logaka Dec 8, 2025
f665ab3
feat: add NotEmptyFilter validation to Filter class
Logaka Dec 9, 2025
af1004a
feat: expanded filtering for external databases
Logaka Dec 9, 2025
5563e44
feat: add dryRun
Logaka Dec 15, 2025
b011b17
Merge branch 'refs/heads/main' into feat/restore-dryRun
Logaka Dec 15, 2025
31e33e7
feat: change restore classifier variable
Logaka Dec 18, 2025
fb32b57
Merge branch 'main' into feat/backupV2-add-complex-filtering
Logaka Dec 18, 2025
6b56a7d
fix: prevent empty filter from generating invalid WHERE clause
Logaka Dec 18, 2025
891c12f
fix: prevent state-changing logic during dry-run in findSimilarDbByCl…
Logaka Dec 19, 2025
9ba3487
test: add tests for dry-run
Logaka Dec 22, 2025
7380508
refactor: reorganize packages
Logaka Dec 22, 2025
d279bd2
refactor: remove attemptCount, duration fields
Logaka Dec 22, 2025
987e061
Merge branch 'main' into feat/retry-restore
Logaka Dec 23, 2025
398e385
feat: implement retry restore
Logaka Dec 25, 2025
ed61408
refactor: conditional return to stream map
Logaka Dec 25, 2025
a20d0e6
Merge branch 'feat/restore-dryRun' into feat/retry-restore
Logaka Dec 25, 2025
ea34805
refactor: prevent lock method duplication
Logaka Dec 26, 2025
e912a3f
refactor: add validation for RestoreRequest
Logaka Jan 16, 2026
8ad5d86
refactor: make databaseKind join conditional
Logaka Jan 19, 2026
9f6d293
refactor: make kinds validation flexible
Logaka Jan 19, 2026
371fb8a
feat: add new attribute to Classifier entity
Logaka Jan 20, 2026
f405a8e
refactor: change restore processing exceptions
Logaka Jan 20, 2026
8034dbe
refactor: rewrite collision catching logic
Logaka Jan 20, 2026
2ec4e9d
Merge branch 'feat/backupV2-add-complex-filtering' into feat/restore-…
Logaka Jan 21, 2026
a0bf7cd
Merge branch 'feat/retry-restore' into feat/restore-dryRun
Logaka Jan 21, 2026
8856251
chore: reformat code
Logaka Jan 21, 2026
1d55eac
feat: add validation annotations for dto
Logaka Jan 22, 2026
76cdd39
chore: rename method, logs, error messages
Logaka Jan 22, 2026
b108e69
refactor: simplify mapping by removing BackupExternalDelegate
Logaka Jan 22, 2026
5d63dca
feat: prevent restore empty databases
Logaka Jan 26, 2026
2194470
Merge branch 'main' into feat/restore-dryRun
Logaka Jan 26, 2026
5862147
fix: adding missed statuses for OpenApi
Logaka Jan 28, 2026
b85d622
refactor: separate mapping, enriching classifiers operation
Logaka Jan 28, 2026
b3fbe74
fix: remove NOT_STARTED status from aggregate method and fix mapping
Logaka Jan 29, 2026
b56a238
style: remove redundant required attribute
Logaka Jan 29, 2026
98874ae
style: fix OpenApi spec
Logaka Jan 30, 2026
1260506
feat: add new flyway migration that mark all status fields in entitie…
Logaka Jan 30, 2026
09d947b
fix: add default status to logical backup
Logaka Jan 30, 2026
d4a010f
fix: take out try catch block from transactional method
Logaka Jan 30, 2026
76838e3
chore: remove unused imports
Logaka Jan 30, 2026
ed2b81e
refactor: invert methods
Logaka Jan 30, 2026
ec959f2
refactor: replace entity builder with constructor
Logaka Jan 30, 2026
d313d81
refactor: replace entity builder with constructor
Logaka Feb 2, 2026
8d49e74
feat: replace auto generating id to manually
Logaka Feb 2, 2026
4a4b0ab
feat: rewrite retryRestore
Logaka Feb 2, 2026
a1d76c3
Merge branch 'main' into feat/restore-dryRun
ArkuNC Feb 3, 2026
157b3a0
style: detailed OpenApi
Logaka Feb 5, 2026
0b72355
chore: rename entities and dtos
Logaka Feb 5, 2026
d14faa0
style: update OpenApi
Logaka Feb 5, 2026
b4d300b
chore: update entity
Logaka Feb 5, 2026
948be71
refactor: simplify first classifier selection
Logaka Feb 5, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;

import jakarta.persistence.AttributeConverter;

import java.io.IOException;
import java.util.SortedMap;

Expand All @@ -24,7 +24,8 @@ public String convertToDatabaseColumn(SortedMap<Object, Object> attribute) {
@Override
public SortedMap<Object, Object> convertToEntityAttribute(String dbData) {
try {
return objectMapper.readValue(dbData, new TypeReference<SortedMap<Object, Object>>() {});
return objectMapper.readValue(dbData, new TypeReference<SortedMap<Object, Object>>() {
});
} catch (IOException e) {
throw new RuntimeException(e);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.netcracker.cloud.dbaas.dao.jpa;

import com.netcracker.cloud.dbaas.dto.backupV2.Filter;
import com.netcracker.cloud.dbaas.entity.pg.Database;
import com.netcracker.cloud.dbaas.entity.pg.DatabaseRegistry;
import com.netcracker.cloud.dbaas.repositories.dbaas.DatabaseRegistryDbaasRepository;
Expand All @@ -12,23 +13,18 @@
import jakarta.persistence.EntityManager;
import jakarta.transaction.Transactional;
import lombok.extern.slf4j.Slf4j;

import net.jodah.failsafe.Failsafe;
import net.jodah.failsafe.RetryPolicy;
import org.apache.commons.lang.StringUtils;

import javax.annotation.Nullable;
import java.time.Duration;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Nullable;

import static com.netcracker.cloud.dbaas.Constants.MICROSERVICE_NAME;
import static com.netcracker.cloud.dbaas.Constants.ROLE;
import static com.netcracker.cloud.dbaas.Constants.SCOPE;
import static com.netcracker.cloud.dbaas.Constants.SCOPE_VALUE_TENANT;
import static com.netcracker.cloud.dbaas.Constants.*;
import static com.netcracker.cloud.dbaas.config.ServicesConfig.DBAAS_REPOSITORIES_MUTEX;
import static jakarta.transaction.Transactional.TxType.REQUIRES_NEW;

Expand Down Expand Up @@ -141,6 +137,11 @@ public List<DatabaseRegistry> findAllTransactionalDatabaseRegistries(String name
return databaseRegistryRepository.findAllByNamespaceAndDatabase_BgVersionNull(namespace);
}

@Override
public List<DatabaseRegistry> findAllDatabasesByFilter(List<Filter> filters) {
return databaseRegistryRepository.findAllDatabasesByFilter(filters);
}

@Override
public void delete(DatabaseRegistry databaseRegistry) {
log.debug("Delete logical database with classifier {} and type {}", databaseRegistry.getClassifier(), databaseRegistry.getType());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.netcracker.cloud.dbaas.dto.backupV2;

import com.netcracker.cloud.dbaas.enums.ExternalDatabaseStrategy;
import com.netcracker.cloud.dbaas.utils.validation.BackupGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.BackupGroup;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.netcracker.cloud.dbaas.enums.BackupStatus;
import com.netcracker.cloud.dbaas.enums.ExternalDatabaseStrategy;
import com.netcracker.cloud.dbaas.utils.validation.BackupGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.BackupGroup;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.netcracker.cloud.dbaas.dto.backupV2;

import com.netcracker.cloud.dbaas.enums.ClassifierType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.SortedMap;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ClassifierResponse {
private ClassifierType type;
private SortedMap<String, Object> classifier;
private SortedMap<String, Object> classifierBeforeMapper;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.netcracker.cloud.dbaas.dto.backupV2;

import com.netcracker.cloud.dbaas.utils.validation.NotEmptyFilter;
import com.netcracker.cloud.dbaas.utils.validation.group.BackupGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.RestoreGroup;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
Expand All @@ -9,6 +12,7 @@
import java.util.List;

@Data
@NotEmptyFilter(groups = {BackupGroup.class, RestoreGroup.class})
@NoArgsConstructor
@Schema(description = "Single filter criteria for backup and restore operations")
public class Filter {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.netcracker.cloud.dbaas.dto.backupV2;

import com.netcracker.cloud.dbaas.utils.validation.BackupGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.BackupGroup;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.microprofile.openapi.annotations.media.Schema;

import java.util.ArrayList;
import java.util.List;

@Data
Expand All @@ -23,13 +25,11 @@ public class FilterCriteria {
)
@NotNull(groups = {BackupGroup.class})
@Size(min = 1, groups = {BackupGroup.class})
private List<Filter> filter;
@Schema(
description = "Include databases that match any of the filters in the list"
)
private List<Filter> include;
@Valid
private List<Filter> filter = new ArrayList<>();

@Schema(
description = "Exclude databases that match any of the filters in the list"
)
private List<Filter> exclude;
private List<Filter> exclude = new ArrayList<>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class RestoreDatabaseResponse {
description = "List of database classifiers. Each classifier is a sorted map of attributes.",
examples = "[{\"namespace\":\"namespace\", \"microserviceName\":\"microserviceName\", \"scope\":\"service\"}]"
)
private List<Map<String, Object>> classifiers;
private List<ClassifierResponse> classifiers;
@Schema(
description = "List of database users",
examples = "[{\"name\":\"username\",\"role\":\"admin\"}"
Expand Down Expand Up @@ -58,7 +58,7 @@ public class RestoreDatabaseResponse {
required = true
)
private String path;
@Schema(description = "Error message if the backup failed", examples = "Restore Not Found")
@Schema(description = "Error message if the backup failed", examples = "Restore Not Found")
private String errorMessage;
@Schema(description = "Timestamp when the restore was created", examples = "2025-11-13T12:34:56Z")
private Instant creationTime;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import org.eclipse.microprofile.openapi.annotations.media.Schema;

import java.util.List;
import java.util.SortedMap;

@Data
@NoArgsConstructor
Expand All @@ -19,6 +18,6 @@ public class RestoreExternalDatabaseResponse {
description = "List of database classifiers. Each classifier is a sorted map of attributes.",
examples = "[{\"namespace\":\"namespace\", \"microserviceName\":\"microserviceName\", \"scope\":\"service\"}]"
)
private List<SortedMap<String, Object>> classifiers;
private List<ClassifierResponse> classifiers;
}

Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.netcracker.cloud.dbaas.dto.backupV2;

import com.netcracker.cloud.dbaas.enums.ExternalDatabaseStrategy;
import com.netcracker.cloud.dbaas.utils.validation.RestoreGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.RestoreGroup;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.ConvertGroup;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.netcracker.cloud.dbaas.enums.ExternalDatabaseStrategy;
import com.netcracker.cloud.dbaas.enums.RestoreStatus;
import com.netcracker.cloud.dbaas.utils.validation.RestoreGroup;
import com.netcracker.cloud.dbaas.utils.validation.group.RestoreGroup;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.ConvertGroup;
Expand Down Expand Up @@ -89,10 +89,6 @@ public class RestoreResponse {
examples = "Backup Not Found"
)
private String errorMessage;
@Schema(description = "Aggregated duration of databases", examples = "1200")
private Long duration;
@Schema(description = "Total number of adapter requests", examples = "1")
private Integer attemptCount;
@Schema(
description = "List of logical restores",
implementation = LogicalRestoreResponse.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.netcracker.cloud.dbaas.entity.dto.backupV2;

import com.netcracker.cloud.dbaas.entity.pg.backupV2.Classifier;
import com.netcracker.cloud.dbaas.entity.pg.backupV2.BackupDatabase;

import java.util.List;
import java.util.SortedMap;


public record BackupDatabaseDelegate(BackupDatabase backupDatabase,
List<SortedMap<String, Object>> classifiers) {}
List<Classifier> classifiers) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.netcracker.cloud.dbaas.entity.dto.backupV2;

import com.netcracker.cloud.dbaas.entity.pg.backupV2.Classifier;
import com.netcracker.cloud.dbaas.entity.pg.backupV2.BackupExternalDatabase;

import java.util.List;

public record BackupExternalDelegate(BackupExternalDatabase backupExternalDatabase, List<Classifier> classifiers) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.netcracker.cloud.dbaas.entity.pg.backupV2;

import com.netcracker.cloud.dbaas.enums.ClassifierType;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Objects;
import java.util.SortedMap;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Classifier {
private ClassifierType type;
private SortedMap<String, Object> classifier;
private SortedMap<String, Object> classifierBeforeMapper;

@Override
public boolean equals(Object o) {
if (!(o instanceof Classifier that)) return false;
return type == that.type && Objects.equals(classifier, that.classifier) && Objects.equals(classifierBeforeMapper, that.classifierBeforeMapper);
}

@Override
public int hashCode() {
return Objects.hash(type, classifier, classifierBeforeMapper);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.time.Instant;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.UUID;

@Data
Expand Down Expand Up @@ -41,7 +40,7 @@ public class RestoreDatabase {
@NotNull
@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition = "jsonb")
private List<SortedMap<String, Object>> classifiers;
private List<Classifier> classifiers;

@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition = "jsonb")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.hibernate.type.SqlTypes;

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

@Data
Expand Down Expand Up @@ -40,5 +39,5 @@ public class RestoreExternalDatabase {
@NotNull
@JdbcTypeCode(SqlTypes.JSON)
@Column(columnDefinition = "jsonb")
private List<SortedMap<String, Object>> classifiers;
private List<Classifier> classifiers;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.netcracker.cloud.dbaas.enums;

public enum ClassifierType {
NEW, REPLACED, TRANSIENT_REPLACED
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.netcracker.cloud.dbaas.dto.Source;
import com.netcracker.cloud.dbaas.dto.backupV2.*;
import com.netcracker.cloud.dbaas.entity.dto.backupV2.BackupExternalDelegate;
import com.netcracker.cloud.dbaas.entity.pg.backupV2.*;
import com.netcracker.cloud.dbaas.enums.BackupTaskStatus;
import com.netcracker.cloud.dbaas.enums.RestoreTaskStatus;
Expand Down Expand Up @@ -100,7 +101,13 @@ private static <T extends Enum<T>, R extends Enum<R>> R mapStatus(
}

@Mapping(target = "id", ignore = true)
RestoreExternalDatabase toRestoreExternalDatabase(BackupExternalDatabase backupExternalDatabase);
@Mapping(target = "name", source = "backupExternalDatabase.name")
@Mapping(target = "type", source = "backupExternalDatabase.type")
@Mapping(target = "classifiers", source = "classifiers")
RestoreExternalDatabase toRestoreExternalDatabase(BackupExternalDelegate backupExternalDelegate);

List<RestoreExternalDatabase> toRestoreExternalDatabases(List<BackupExternalDatabase> backupExternalDatabases);
List<RestoreExternalDatabase> toRestoreExternalDatabases(List<BackupExternalDelegate> backupExternalDelegates);

ClassifierResponse toClassifierResponse(Classifier classifier);
List<ClassifierResponse> toClassifierResponse(List<Classifier> classifiers);
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package com.netcracker.cloud.dbaas.repositories.dbaas;

import com.netcracker.cloud.dbaas.dto.backupV2.Filter;
import com.netcracker.cloud.dbaas.entity.pg.Database;
import com.netcracker.cloud.dbaas.entity.pg.DatabaseRegistry;

import javax.annotation.Nullable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

import javax.annotation.Nullable;

public interface DatabaseRegistryDbaasRepository {
List<DatabaseRegistry> findAnyLogDbRegistryTypeByNamespace(String namespace);

Expand Down Expand Up @@ -63,4 +63,5 @@ public interface DatabaseRegistryDbaasRepository {

List<DatabaseRegistry> findAllTransactionalDatabaseRegistries(String namespace);

List<DatabaseRegistry> findAllDatabasesByFilter(List<Filter> filters);
}
Loading
Loading