roryqi commented on code in PR #13771:
URL: https://github.com/apache/gravitino/pull/13771#discussion_r4266173765
##########
core/src/main/java/org/apache/gravitino/catalog/TableOperationDispatcher.java:
##########
@@ -177,16 +178,27 @@ public Table loadTable(NameIdentifier ident) throws
NoSuchTableException {
entityCombinedTable =
TreeLockUtils.doWithTreeLock(schemaIdent, LockType.WRITE, () ->
importTable(ident));
} catch (EntityAlreadyExistsException e) {
- // HA race: another Gravitino node concurrently imported this table.
Reload from the
- // entity store to pick up the entity stored by the winning node.
- LOG.info(
- "Table {} was concurrently imported by another node; reloading
from store.", ident);
+ // A create-only import can conflict either because another Gravitino
node won an HA race,
+ // or because the external identifier is already stored under another
Gravitino path.
+ // Reload to distinguish a successful concurrent import from an
identity conflict.
+ LOG.info("Table {} import conflicted with existing metadata; reloading
from store.", ident);
entityCombinedTable =
TreeLockUtils.doWithTreeLock(ident, LockType.READ, () ->
internalLoadTable(ident));
if (!entityCombinedTable.imported()) {
throw new UnsupportedOperationException(
- "Table managed by multiple catalogs. This may cause unexpected
issues such as privilege conflicts. "
- + "To resolve: Remove all catalogs managing this table, then
recreate one catalog to ensure single-catalog management.");
+ "Table "
+ + ident
+ + " cannot be imported because its name or external
identifier is already "
+ + "managed under a different Gravitino identifier. Gravitino
does not "
+ + "automatically reconcile external table renames or stale
registrations. "
+ + "Before retrying, manually resolve the conflict: either
restore the external "
+ + "table name and identifier to match its Gravitino
registration, or have an "
+ + "administrator safely remove the stale Gravitino
registration and its "
+ + "privileges, tags, and other relationships. Do not only
remove "
+ + "`gravitino.identifier` while the conflicting registration
remains, because "
+ + "Gravitino may associate the external table with that
registration. After the "
+ + "stale registration is removed, clear
`gravitino.identifier` from the external "
+ + "table and load it again.");
Review Comment:
Addressed in 69495771f8.
The schema, table, and view conflict messages now use a shared helper and no
longer prescribe an unavailable object-level cleanup operation. They explicitly
state that Gravitino has no metadata-only unregister for an individual external
object and describe the supported catalog-wide recovery: force-drop and
recreate the containing Gravitino catalog registration. The message also warns
that this removes every stored registration and its privileges, tags, and other
relationships, and directs operators to the provider-specific guidance before
clearing external identifiers.
The Hive, Hudi-HMS, Iceberg, and Paimon catalog docs now document the exact
recovery sequence and state which external objects and physical data are
retained. Hudi guidance is conditional because its read-only operations do not
write identifiers: an external HMS tool is needed only when an affected object
actually carries `gravitino.identifier`.
The schema/table/view dispatcher tests and `./gradlew :docs:build` pass. I
am leaving this thread unresolved for reviewer confirmation.
--
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]