Skip to content

Commit 7f1d67a

Browse files
committed
Move the data upgrade process to the v2 endpoint and improve references management
1 parent 61d3090 commit 7f1d67a

File tree

8 files changed

+71
-137
lines changed

8 files changed

+71
-137
lines changed

app/src/main/java/io/apicurio/registry/rest/v2/AdminResourceImpl.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import io.apicurio.registry.types.RuleType;
3939
import io.apicurio.registry.types.provider.ArtifactTypeUtilProviderFactory;
4040
import io.apicurio.registry.utils.impexp.Entity;
41-
import io.apicurio.registry.utils.impexp.v3.EntityReader;
41+
import io.apicurio.registry.utils.impexp.v2.EntityReader;
4242
import jakarta.enterprise.context.ApplicationScoped;
4343
import jakarta.inject.Inject;
4444
import jakarta.interceptor.Interceptors;
@@ -264,7 +264,7 @@ public void close() throws IOException {
264264
zip.close();
265265
}
266266
};
267-
this.storage.importData(stream, isNullOrTrue(xRegistryPreserveGlobalId),
267+
this.storage.upgradeData(stream, isNullOrTrue(xRegistryPreserveGlobalId),
268268
isNullOrTrue(xRegistryPreserveContentId));
269269
}
270270

app/src/main/java/io/apicurio/registry/storage/importing/v2/SqlDataUpgrader.java

+53-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.apicurio.registry.model.GAV;
66
import io.apicurio.registry.storage.RegistryStorage;
77
import io.apicurio.registry.storage.dto.ArtifactReferenceDto;
8+
import io.apicurio.registry.storage.dto.EditableArtifactMetaDataDto;
89
import io.apicurio.registry.storage.error.InvalidArtifactTypeException;
910
import io.apicurio.registry.storage.error.VersionAlreadyExistsException;
1011
import io.apicurio.registry.storage.impexp.EntityInputStream;
@@ -61,6 +62,12 @@ public class SqlDataUpgrader extends AbstractDataImporter {
6162
protected final Map<Long, Long> globalIdMapping = new HashMap<>();
6263
protected final Map<Long, Long> contentIdMapping = new HashMap<>();
6364

65+
// Collection of content waiting for required references. A given content cannot be imported unless the
66+
// expected reference is present.
67+
// TODO do a second round to this, since this currently means enforcing the integrity rule. (Maybe try a
68+
// first round and, if there are no artifacts remaining, just import the orphaned content).
69+
protected final Map<ContentEntity, Set<GAV>> waitingForReference = new HashMap<>();
70+
6471
// To keep track of which versions have been imported
6572
private final Set<GAV> gavDone = new HashSet<>();
6673

@@ -126,7 +133,7 @@ public void importArtifactVersion(ArtifactVersionEntity entity) {
126133
.groupId(entity.groupId).build();
127134

128135
// If the version being imported is the first one, we have to create the artifact first
129-
if (entity.versionId == 1) {
136+
if (!storage.isArtifactExists(entity.groupId, entity.artifactId)) {
130137
ArtifactEntity artifactEntity = ArtifactEntity.builder().artifactId(entity.artifactId)
131138
.artifactType(entity.artifactType).createdOn(entity.createdOn)
132139
.description(entity.description).groupId(entity.groupId).labels(artifactVersionLabels)
@@ -135,6 +142,16 @@ public void importArtifactVersion(ArtifactVersionEntity entity) {
135142
storage.importArtifact(artifactEntity);
136143
}
137144

145+
if (entity.isLatest) {
146+
// If this version is the latest, update the artifact metadata with its metadata
147+
EditableArtifactMetaDataDto editableArtifactMetaDataDto = EditableArtifactMetaDataDto
148+
.builder().name(newEntity.name).owner(newEntity.owner)
149+
.description(newEntity.description).labels(newEntity.labels).build();
150+
151+
storage.updateArtifactMetaData(newEntity.groupId, newEntity.artifactId,
152+
editableArtifactMetaDataDto);
153+
}
154+
138155
storage.importArtifactVersion(newEntity);
139156
log.debug("Artifact version imported successfully: {}", entity);
140157
globalIdMapping.put(oldGlobalId, entity.globalId);
@@ -149,6 +166,20 @@ public void importArtifactVersion(ArtifactVersionEntity entity) {
149166
}
150167
waitingForVersion.removeAll(commentsToImport);
151168

169+
// Once the artifact version is processed, check if there is some content waiting for this as it's
170+
// reference
171+
// For each content waiting for the version we just inserted, remove it from the list.
172+
waitingForReference.values().forEach(waitingReferences -> waitingReferences.remove(gav));
173+
174+
// Finally, once the list of required deps is updated, if it was the last reference needed, import
175+
// the content.
176+
waitingForReference.keySet().stream()
177+
.filter(content -> waitingForReference.get(content).isEmpty())
178+
.forEach(contentToImport -> {
179+
if (!contentIdMapping.containsKey(contentToImport.contentId)) {
180+
importContent(contentToImport);
181+
}
182+
});
152183
} catch (VersionAlreadyExistsException ex) {
153184
if (ex.getGlobalId() != null) {
154185
log.warn("Duplicate globalId {} detected, skipping import of artifact version: {}",
@@ -167,6 +198,27 @@ public void importContent(ContentEntity entity) {
167198
List<ArtifactReferenceDto> references = SqlUtil
168199
.deserializeReferences(entity.serializedReferences);
169200

201+
Set<GAV> referencesGavs = references
202+
.stream().map(referenceDto -> new GAV(referenceDto.getGroupId(),
203+
referenceDto.getArtifactId(), referenceDto.getVersion()))
204+
.collect(Collectors.toSet());
205+
206+
Set<ArtifactReferenceDto> requiredReferences = new HashSet<>();
207+
208+
// If there are references and they've not been imported yet, add them to the waiting collection
209+
if (!references.isEmpty() && !gavDone.containsAll(referencesGavs)) {
210+
waitingForReference.put(entity, referencesGavs);
211+
212+
// For each artifact reference, if it has not been imported yet, add it to the waiting list
213+
// for this content.
214+
referencesGavs.stream()
215+
.filter(artifactReference -> !referencesGavs.contains(artifactReference))
216+
.forEach(artifactReference -> waitingForReference.get(entity).add(artifactReference));
217+
218+
// This content cannot be imported until all the references are imported.
219+
return;
220+
}
221+
170222
TypedContent typedContent = TypedContent.create(ContentHandle.create(entity.contentBytes), null);
171223
Map<String, TypedContent> resolvedReferences = storage.resolveReferences(references);
172224
entity.artifactType = utils.determineArtifactType(typedContent, null, resolvedReferences);

app/src/main/java/io/apicurio/registry/upgrade/v2/DataUpgrader.java

-82
This file was deleted.

app/src/test/java/io/apicurio/registry/DataUpgradeTest.java

+15-19
Original file line numberDiff line numberDiff line change
@@ -3,40 +3,36 @@
33
import io.apicurio.registry.model.GroupId;
44
import io.apicurio.registry.rest.client.models.ArtifactReference;
55
import io.apicurio.registry.utils.IoUtil;
6-
import io.apicurio.registry.utils.tests.ApicurioTestTags;
76
import io.quarkus.test.junit.QuarkusTest;
8-
import io.quarkus.test.junit.TestProfile;
97
import org.junit.jupiter.api.Assertions;
10-
import org.junit.jupiter.api.BeforeEach;
11-
import org.junit.jupiter.api.Tag;
8+
import org.junit.jupiter.api.BeforeAll;
129
import org.junit.jupiter.api.Test;
1310

11+
import java.io.InputStream;
1412
import java.util.List;
1513

14+
import static io.restassured.RestAssured.given;
15+
import static org.hamcrest.CoreMatchers.anything;
16+
1617
@QuarkusTest
17-
@TestProfile(DataUpgradeTestProfile.class)
18-
@Tag(ApicurioTestTags.SLOW)
1918
public class DataUpgradeTest extends AbstractResourceTestBase {
2019

2120
@Override
22-
@BeforeEach
23-
protected void beforeEach() throws Exception {
21+
@BeforeAll
22+
protected void beforeAll() throws Exception {
23+
super.beforeAll();
24+
2425
setupRestAssured();
25-
}
2626

27-
@Test
28-
public void testArtifactsCount() {
29-
Assertions.assertEquals(26, clientV3.search().artifacts().get().getCount());
27+
try (InputStream data = resourceToInputStream("./upgrade/v2_export.zip")) {
28+
given().when().contentType("application/zip").body(data).post("/registry/v2/admin/import").then()
29+
.statusCode(204).body(anything());
30+
}
3031
}
3132

3233
@Test
33-
public void testCheckGlobalRules() throws Exception {
34-
// Global rules are enabled in the export file, they must be activated.
35-
Assertions.assertEquals(3, clientV3.admin().rules().get().size());
36-
Assertions.assertEquals("FULL", clientV3.admin().rules().byRuleType("VALIDITY").get().getConfig());
37-
Assertions.assertEquals("BACKWARD",
38-
clientV3.admin().rules().byRuleType("COMPATIBILITY").get().getConfig());
39-
Assertions.assertEquals("FULL", clientV3.admin().rules().byRuleType("INTEGRITY").get().getConfig());
34+
public void testArtifactsCount() {
35+
Assertions.assertEquals(32, clientV3.search().artifacts().get().getCount());
4036
}
4137

4238
@Test

app/src/test/java/io/apicurio/registry/DataUpgradeTestProfile.java

-16
This file was deleted.

app/src/test/java/io/apicurio/registry/rbac/AdminResourceTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ void testExportForBrowser() throws Exception {
350350
}
351351

352352
@Test
353-
@Disabled // TODO: Disabled, so I can submit the import/export migration feature in a separate PR.
353+
@Disabled// TODO: Disabled, so I can submit the import/export migration feature in a separate PR.
354354
void testImport() throws Exception {
355355
var result = clientV3.search().artifacts().get(config -> {
356356
config.queryParameters.offset = 0;
Binary file not shown.

docs/modules/ROOT/partials/getting-started/ref-registry-all-configs.adoc

-16
Original file line numberDiff line numberDiff line change
@@ -826,19 +826,3 @@ The following {registry} configuration options are available for each component
826826
|Navigation prefix for all UI paths
827827
|===
828828

829-
== upgrade
830-
.upgrade configuration options
831-
[.table-expandable,width="100%",cols="6,3,2,3,5",options="header"]
832-
|===
833-
|Name
834-
|Type
835-
|Default
836-
|Available from
837-
|Description
838-
|`apicurio.upgrade.file.location`
839-
|`optional<url>`
840-
|
841-
|`3.0.0`
842-
|The URL to a v2 export file
843-
|===
844-

0 commit comments

Comments
 (0)