Copilot commented on code in PR #7815:
URL: https://github.com/apache/ignite-3/pull/7815#discussion_r2965273410
##########
modules/partition-replicator/src/main/java/org/apache/ignite/internal/partition/replicator/schema/CatalogValidationSchemasSource.java:
##########
@@ -155,56 +166,48 @@ private Stream<SimpleEntry<Catalog,
CatalogTableDescriptor>> tableVersionsBetwee
.takeWhile(Objects::nonNull);
}
- private static FullTableSchema fullSchemaFromCatalog(Catalog catalog,
CatalogTableDescriptor tableDescriptor) {
+ private FullTableSchema fullSchemaFromCatalog(Catalog catalog,
CatalogTableDescriptor tableDescriptor) {
assert tableDescriptor != null;
+ Int2IntMap indexesJustStartedBeingBuilt =
indexesJustStartedBeingBuilt(tableDescriptor, catalog);
+
return new FullTableSchema(
catalog.version(),
tableDescriptor.latestSchemaVersion(),
tableDescriptor.id(),
tableDescriptor.name(),
- tableDescriptor.columns()
+ tableDescriptor.columns(),
+ indexesJustStartedBeingBuilt
);
}
- private static class CatalogVersionsSpan {
- private final int tableId;
- private final int fromCatalogVersion;
- private final int toCatalogVersion;
-
- private CatalogVersionsSpan(int tableId, int fromCatalogVersion, int
toCatalogVersion) {
- this.tableId = tableId;
- this.fromCatalogVersion = fromCatalogVersion;
- this.toCatalogVersion = toCatalogVersion;
- }
+ private Int2IntMap indexesJustStartedBeingBuilt(CatalogTableDescriptor
tableDescriptor, Catalog catalog) {
+ Int2IntMap indexesJustStartedBeingBuilt = new Int2IntOpenHashMap();
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
+ for (CatalogIndexDescriptor index :
catalog.indexes(tableDescriptor.id())) {
+ if (index.status() == CatalogIndexStatus.BUILDING) {
Review Comment:
`indexesJustStartedBeingBuilt` always allocates an `Int2IntOpenHashMap` even
when there are no BUILDING indexes. Since this method is called for every
catalog version processed, consider allocating lazily (start with
`Int2IntMaps.EMPTY_MAP` / `null` and create the map only on the first match) to
reduce allocations and GC pressure.
##########
modules/partition-replicator/src/main/java/org/apache/ignite/internal/partition/replicator/schema/CatalogValidationSchemasSource.java:
##########
@@ -155,56 +166,48 @@ private Stream<SimpleEntry<Catalog,
CatalogTableDescriptor>> tableVersionsBetwee
.takeWhile(Objects::nonNull);
}
- private static FullTableSchema fullSchemaFromCatalog(Catalog catalog,
CatalogTableDescriptor tableDescriptor) {
+ private FullTableSchema fullSchemaFromCatalog(Catalog catalog,
CatalogTableDescriptor tableDescriptor) {
assert tableDescriptor != null;
+ Int2IntMap indexesJustStartedBeingBuilt =
indexesJustStartedBeingBuilt(tableDescriptor, catalog);
+
return new FullTableSchema(
catalog.version(),
tableDescriptor.latestSchemaVersion(),
tableDescriptor.id(),
tableDescriptor.name(),
- tableDescriptor.columns()
+ tableDescriptor.columns(),
+ indexesJustStartedBeingBuilt
);
}
- private static class CatalogVersionsSpan {
- private final int tableId;
- private final int fromCatalogVersion;
- private final int toCatalogVersion;
-
- private CatalogVersionsSpan(int tableId, int fromCatalogVersion, int
toCatalogVersion) {
- this.tableId = tableId;
- this.fromCatalogVersion = fromCatalogVersion;
- this.toCatalogVersion = toCatalogVersion;
- }
+ private Int2IntMap indexesJustStartedBeingBuilt(CatalogTableDescriptor
tableDescriptor, Catalog catalog) {
+ Int2IntMap indexesJustStartedBeingBuilt = new Int2IntOpenHashMap();
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
+ for (CatalogIndexDescriptor index :
catalog.indexes(tableDescriptor.id())) {
+ if (index.status() == CatalogIndexStatus.BUILDING) {
+ IndexMeta indexMeta = indexMetasAccess.indexMeta(index.id());
+ if (indexMeta == null) {
+ throw new IllegalStateException(
+ "Index " + index.id() + " is not in the index
metastore even though it's being built, according to the catalog"
+ );
+ }
- CatalogVersionsSpan that = (CatalogVersionsSpan) o;
+ MetaIndexStatusChange changeToBuilding =
indexMeta.statusChange(MetaIndexStatus.BUILDING);
+ if (changeToBuilding == null) {
+ throw new IllegalStateException(
+ "Index " + index.id() + " is being built, but its
status was never changed to BUILDING"
+ );
+ }
- if (tableId != that.tableId) {
- return false;
- }
- if (fromCatalogVersion != that.fromCatalogVersion) {
- return false;
+ if (catalog.version() == changeToBuilding.catalogVersion()) {
+ // The index has just become being built.
+ indexesJustStartedBeingBuilt.put(index.id(),
indexMeta.statusChange(MetaIndexStatus.REGISTERED).catalogVersion());
+ }
Review Comment:
`IndexMeta.statusChange(...)` never returns null (it throws
`IllegalArgumentException` when absent), so the `changeToBuilding == null`
branch is dead code and the thrown exception will currently bypass this more
descriptive error message. Consider using `statusChangeNullable` (and handling
null explicitly) or catching `IllegalArgumentException` to rethrow with
context; same applies to `statusChange(REGISTERED)` which can also throw and
currently isn't guarded.
##########
modules/partition-replicator/src/main/java/org/apache/ignite/internal/partition/replicator/schemacompat/SchemaCompatibilityValidator.java:
##########
@@ -138,14 +141,26 @@ private CompatValidationResult
validateForwardSchemaCompatibility(
assert !tableSchemas.isEmpty() : "No table schemas for table " +
tableId + " between " + beginTimestamp + " and " + commitTimestamp;
+ int initialSchemaCatalogVersion = tableSchemas.get(0).catalogVersion();
+ int commitSchemaCatalogVersion = tableSchemas.get(tableSchemas.size()
- 1).catalogVersion();
+
+ return forwardCompatValidationResultCache.computeIfAbsent(
+ new CatalogVersionsSpan(tableId, initialSchemaCatalogVersion,
commitSchemaCatalogVersion),
+ key ->
validateForwardSchemaCompatibility(initialSchemaCatalogVersion, tableSchemas)
+ );
Review Comment:
`forwardCompatValidationResultCache` is now keyed by `(tableId,
fromCatalogVersion, toCatalogVersion)`, which can create many more cache
entries than the previous per-adjacent-diff cache (potentially O(n^2) spans per
table as transactions commit across varying ranges). If this cache is expected
to be long-lived (see the existing TODO about compaction), consider returning
to per-step caching for context-free validators and applying the
context-dependent check (`IndexStartedBuildingValidator`) without caching (or
use a bounded/evicting cache) to avoid unbounded growth.
```suggestion
return
validateForwardSchemaCompatibility(initialSchemaCatalogVersion, tableSchemas);
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]