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.\n\nThe 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.\n\nThe 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's 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 .\n\nThe schema/table/view
dispatcher tests and
> Configure project :
------------------ Check Docker environment ---------------------
Docker server status ............................................ [running]
Run test cases without `gravitino-docker-test` tag .............. [embedded
test]
-----------------------------------------------------------------
> Configure project :catalogs
Path for java installation '/usr/lib/jvm/openjdk-17' (Common Linux
Locations) does not contain a java executable
> Configure project :core
Kotlin DSL property assignment is an incubating feature.
> Task :docs:processResources NO-SOURCE
> Task :spotlessInternalRegisterDependencies UP-TO-DATE
> Task :docs:generateMavenLegalFiles UP-TO-DATE
> Task :docs:spotlessJava UP-TO-DATE
> Task :docs:spotlessJavaCheck UP-TO-DATE
> Task :docs:spotlessKotlinGradle UP-TO-DATE
> Task :docs:spotlessKotlinGradleCheck UP-TO-DATE
> Task :docs:spotlessCheck UP-TO-DATE
> Task :docs:compileJava NO-SOURCE
> Task :docs:classes UP-TO-DATE
> Task :docs:jar UP-TO-DATE
> Task :docs:assemble UP-TO-DATE
> Task :docs:compileTestJava NO-SOURCE
> Task :docs:processTestResources NO-SOURCE
> Task :docs:testClasses UP-TO-DATE
> Task :docs:test NO-SOURCE
> Task :docs:jacocoTestReport SKIPPED
> Task :docs:check UP-TO-DATE
> Task :docs:nodeSetup UP-TO-DATE
> Task :docs:npmSetup UP-TO-DATE
> Task :docs:lintIdpOpenAPI
> Task :docs:lintOpenAPI
> Task :docs:build
Deprecated Gradle features were used in this build, making it incompatible
with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings
and determine if they come from your own scripts or plugins.
For more on this, please refer to
https://docs.gradle.org/8.2/userguide/command_line_interface.html#sec:command_line_warnings
in the Gradle documentation.
BUILD SUCCESSFUL in 13s
11 actionable tasks: 2 executed, 9 up-to-date 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]