This is an automated email from the ASF dual-hosted git repository.
jshao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git
The following commit(s) were added to refs/heads/main by this push:
new f99d3c9815 [#7380] feat(model): Add multiple URIs APIs for model
version (#7386)
f99d3c9815 is described below
commit f99d3c9815d682a9ed8a2aacc552d1d6002fd589
Author: XiaoZ <[email protected]>
AuthorDate: Tue Jun 24 20:02:49 2025 +0800
[#7380] feat(model): Add multiple URIs APIs for model version (#7386)
### What changes were proposed in this pull request?
Add multiple URIs APIs for model version.
### Why are the changes needed?
Fix: #7380
### Does this PR introduce _any_ user-facing change?
No, not implemented yet.
### How was this patch tested?
Existing tests.
---------
Co-authored-by: zhanghan <[email protected]>
---
.../NoSuchModelVersionURINameException.java | 48 ++++++++++
.../org/apache/gravitino/model/ModelCatalog.java | 65 +++++++++++++-
.../org/apache/gravitino/model/ModelVersion.java | 27 +++++-
.../fileset/TestFilesetCatalogOperations.java | 12 +++
.../gravitino/catalog/hive/TestHiveCatalog.java | 6 ++
.../catalog/kafka/TestKafkaCatalogOperations.java | 6 ++
.../lakehouse/hudi/TestHudiCatalogOperations.java | 6 ++
.../lakehouse/iceberg/TestIcebergCatalog.java | 6 ++
.../lakehouse/paimon/TestPaimonCatalog.java | 6 ++
.../gravitino/catalog/model/ModelCatalogImpl.java | 8 ++
.../catalog/model/ModelPropertiesMetadata.java | 17 +++-
...ta.java => ModelVersionPropertiesMetadata.java} | 19 +++-
.../gravitino/api/model/model_version.py | 23 ++++-
.../gravitino/client/generic_model_catalog.py | 100 +++++++++++++++++++++
.../gravitino/client/generic_model_version.py | 3 +
.../gravitino/dto/model_version_dto.py | 3 +
clients/client-python/gravitino/exceptions/base.py | 4 +
.../exceptions/handlers/model_error_handler.py | 3 +
.../catalog/ModelOperationDispatcher.java | 27 ++++--
.../apache/gravitino/connector/BaseCatalog.java | 6 ++
.../gravitino/connector/HasPropertyMetadata.java | 8 ++
.../java/org/apache/gravitino/TestCatalog.java | 5 ++
22 files changed, 387 insertions(+), 21 deletions(-)
diff --git
a/api/src/main/java/org/apache/gravitino/exceptions/NoSuchModelVersionURINameException.java
b/api/src/main/java/org/apache/gravitino/exceptions/NoSuchModelVersionURINameException.java
new file mode 100644
index 0000000000..2d7eadeeff
--- /dev/null
+++
b/api/src/main/java/org/apache/gravitino/exceptions/NoSuchModelVersionURINameException.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.gravitino.exceptions;
+
+import com.google.errorprone.annotations.FormatMethod;
+
+/** Exception thrown when a URI name of model version is not found. */
+public class NoSuchModelVersionURINameException extends NotFoundException {
+
+ /**
+ * Constructs a new exception with the specified detail message.
+ *
+ * @param message the detail message.
+ * @param args the arguments to the message.
+ */
+ @FormatMethod
+ public NoSuchModelVersionURINameException(String message, Object... args) {
+ super(message, args);
+ }
+
+ /**
+ * Constructs a new exception with the specified detail message and cause.
+ *
+ * @param cause the cause.
+ * @param message the detail message.
+ * @param args the arguments to the message.
+ */
+ @FormatMethod
+ public NoSuchModelVersionURINameException(Throwable cause, String message,
Object... args) {
+ super(cause, message, args);
+ }
+}
diff --git a/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
b/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
index a2253fdcbe..9ef85ea42b 100644
--- a/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
+++ b/api/src/main/java/org/apache/gravitino/model/ModelCatalog.java
@@ -18,6 +18,9 @@
*/
package org.apache.gravitino.model;
+import static org.apache.gravitino.model.ModelVersion.URI_NAME_UNKNOWN;
+
+import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
@@ -26,6 +29,7 @@ import
org.apache.gravitino.exceptions.ModelAlreadyExistsException;
import
org.apache.gravitino.exceptions.ModelVersionAliasesAlreadyExistException;
import org.apache.gravitino.exceptions.NoSuchModelException;
import org.apache.gravitino.exceptions.NoSuchModelVersionException;
+import org.apache.gravitino.exceptions.NoSuchModelVersionURINameException;
import org.apache.gravitino.exceptions.NoSuchSchemaException;
/**
@@ -219,13 +223,70 @@ public interface ModelCatalog {
* @throws NoSuchModelException If the model does not exist.
* @throws ModelVersionAliasesAlreadyExistException If the aliases already
exist in the model.
*/
- void linkModelVersion(
+ default void linkModelVersion(
NameIdentifier ident,
String uri,
String[] aliases,
String comment,
Map<String, String> properties)
- throws NoSuchModelException, ModelVersionAliasesAlreadyExistException;
+ throws NoSuchModelException, ModelVersionAliasesAlreadyExistException {
+ linkModelVersion(ident, ImmutableMap.of(URI_NAME_UNKNOWN, uri), aliases,
comment, properties);
+ }
+
+ /**
+ * Link a new model version to the registered model object. The new model
version will be added to
+ * the model object. If the model object does not exist, it will throw an
exception. If the
+ * version alias already exists in the model, it will throw an exception.
+ *
+ * @param ident The name identifier of the model.
+ * @param uris The names and URIs of the model version artifact.
+ * @param aliases The aliases of the model version. The aliases should be
unique in this model,
+ * otherwise the {@link ModelVersionAliasesAlreadyExistException} will
be thrown. The aliases
+ * are optional and can be empty. Also, be aware that the alias cannot
be a number or a number
+ * string.
+ * @param comment The comment of the model version. The comment is optional
and can be null.
+ * @param properties The properties of the model version. The properties are
optional and can be
+ * null or empty.
+ * @throws NoSuchModelException If the model does not exist.
+ * @throws ModelVersionAliasesAlreadyExistException If the aliases already
exist in the model.
+ */
+ default void linkModelVersion(
+ NameIdentifier ident,
+ Map<String, String> uris,
+ String[] aliases,
+ String comment,
+ Map<String, String> properties)
+ throws NoSuchModelException, ModelVersionAliasesAlreadyExistException {
+ throw new UnsupportedOperationException("Not supported yet");
+ }
+
+ /**
+ * Get the URI of the model artifact with a specified version number and URI
name.
+ *
+ * @param ident The name identifier of the model.
+ * @param version The version number of the model.
+ * @param uriName The name of the URI. If null, the default URI will be used.
+ * @throws NoSuchModelVersionException If the model version does not exist.
+ * @return The URI of the model version.
+ */
+ default String getModelVersionUri(NameIdentifier ident, int version, String
uriName)
+ throws NoSuchModelVersionException, NoSuchModelVersionURINameException {
+ throw new UnsupportedOperationException("Not supported yet");
+ }
+
+ /**
+ * Get the URI of the model artifact with a specified version alias and URI
name.
+ *
+ * @param ident The name identifier of the model.
+ * @param alias The version alias of the model.
+ * @param uriName The name of the URI. If null, the default URI will be used.
+ * @throws NoSuchModelVersionException If the model version does not exist.
+ * @return The URI of the model version.
+ */
+ default String getModelVersionUri(NameIdentifier ident, String alias, String
uriName)
+ throws NoSuchModelVersionException, NoSuchModelVersionURINameException {
+ throw new UnsupportedOperationException("Not supported yet");
+ }
/**
* Delete the model version by the {@link NameIdentifier} and version
number. If the model version
diff --git a/api/src/main/java/org/apache/gravitino/model/ModelVersion.java
b/api/src/main/java/org/apache/gravitino/model/ModelVersion.java
index 2557c86077..5f6fa5bf42 100644
--- a/api/src/main/java/org/apache/gravitino/model/ModelVersion.java
+++ b/api/src/main/java/org/apache/gravitino/model/ModelVersion.java
@@ -31,6 +31,12 @@ import org.apache.gravitino.annotation.Evolving;
@Evolving
public interface ModelVersion extends Auditable {
+ /** The property name for the default uri name of the model version. */
+ String PROPERTY_DEFAULT_URI_NAME = "default-uri-name";
+
+ /** The reserved URI name to indicate the URI name is unknown. */
+ String URI_NAME_UNKNOWN = "unknown";
+
/**
* The version of this model object. The version number is an integer number
starts from 0. Each
* time the model checkpoint / snapshot is linked to the registered, the
version number will be
@@ -60,12 +66,27 @@ public interface ModelVersion extends Auditable {
String[] aliases();
/**
- * The URI of the model artifact. The URI is the location of the model
artifact. The URI can be a
- * file path or a remote URI.
+ * The unnamed URI of the model artifact. The URI is the location of the
model artifact. The URI
+ * can be a file path or a remote URI.
*
* @return The URI of the model artifact.
*/
- String uri();
+ default String uri() {
+ return uris().get(URI_NAME_UNKNOWN);
+ }
+
+ /**
+ * The name and corresponding URI of the model artifact. The key is the name
of the URI, and the
+ * value is the URI of the model artifact, which can be a file path or a
remote URI.
+ *
+ * <p>The "unknown" URI name is reserved for the compatibility with single
URI.
+ *
+ * @return The URIs of the model version, the key is the name of the URI and
the value is the URI
+ * of the model artifact.
+ */
+ default Map<String, String> uris() {
+ throw new UnsupportedOperationException("Not implemented yet");
+ }
/**
* The properties of the model version. The properties are key-value pairs
that can be used to
diff --git
a/catalogs/catalog-fileset/src/test/java/org/apache/gravitino/catalog/fileset/TestFilesetCatalogOperations.java
b/catalogs/catalog-fileset/src/test/java/org/apache/gravitino/catalog/fileset/TestFilesetCatalogOperations.java
index e3d7a95ca7..8c4fd4cdd8 100644
---
a/catalogs/catalog-fileset/src/test/java/org/apache/gravitino/catalog/fileset/TestFilesetCatalogOperations.java
+++
b/catalogs/catalog-fileset/src/test/java/org/apache/gravitino/catalog/fileset/TestFilesetCatalogOperations.java
@@ -151,6 +151,12 @@ public class TestFilesetCatalogOperations {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException("Does not support model
properties");
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
private static EntityStore store;
@@ -1184,6 +1190,12 @@ public class TestFilesetCatalogOperations {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
return null;
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ return null;
+ }
};
try {
diff --git
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/TestHiveCatalog.java
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/TestHiveCatalog.java
index 910fe2db70..9528d9b2fb 100644
---
a/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/TestHiveCatalog.java
+++
b/catalogs/catalog-hive/src/test/java/org/apache/gravitino/catalog/hive/TestHiveCatalog.java
@@ -71,6 +71,12 @@ public class TestHiveCatalog extends
MiniHiveMetastoreService {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException("Model properties are not
supported");
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
@Test
diff --git
a/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
b/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
index 007477271d..ef90c81893 100644
---
a/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
+++
b/catalogs/catalog-kafka/src/test/java/org/apache/gravitino/catalog/kafka/TestKafkaCatalogOperations.java
@@ -121,6 +121,12 @@ public class TestKafkaCatalogOperations extends
KafkaClusterEmbedded {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException("Not supported");
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
private static EntityStore store;
private static IdGenerator idGenerator;
diff --git
a/catalogs/catalog-lakehouse-hudi/src/test/java/org/apache/gravitino/catalog/lakehouse/hudi/TestHudiCatalogOperations.java
b/catalogs/catalog-lakehouse-hudi/src/test/java/org/apache/gravitino/catalog/lakehouse/hudi/TestHudiCatalogOperations.java
index a4b86c0c5d..8fb4128b88 100644
---
a/catalogs/catalog-lakehouse-hudi/src/test/java/org/apache/gravitino/catalog/lakehouse/hudi/TestHudiCatalogOperations.java
+++
b/catalogs/catalog-lakehouse-hudi/src/test/java/org/apache/gravitino/catalog/lakehouse/hudi/TestHudiCatalogOperations.java
@@ -64,6 +64,12 @@ public class TestHudiCatalogOperations {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException();
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
@Test
diff --git
a/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/TestIcebergCatalog.java
b/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/TestIcebergCatalog.java
index 8ff70d3985..acd3c3a1f0 100644
---
a/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/TestIcebergCatalog.java
+++
b/catalogs/catalog-lakehouse-iceberg/src/test/java/org/apache/gravitino/catalog/lakehouse/iceberg/TestIcebergCatalog.java
@@ -69,6 +69,12 @@ public class TestIcebergCatalog {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException("Model properties are not
supported");
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
@Test
diff --git
a/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/TestPaimonCatalog.java
b/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/TestPaimonCatalog.java
index 010b6daeef..f7187258f4 100644
---
a/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/TestPaimonCatalog.java
+++
b/catalogs/catalog-lakehouse-paimon/src/test/java/org/apache/gravitino/catalog/lakehouse/paimon/TestPaimonCatalog.java
@@ -77,6 +77,12 @@ public class TestPaimonCatalog {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
throw new UnsupportedOperationException("Model properties are not
supported");
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata()
+ throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Does not support model
version properties");
+ }
};
private static String tempDir =
diff --git
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogImpl.java
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogImpl.java
index 545f6482a3..ba3bfa4984 100644
---
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogImpl.java
+++
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelCatalogImpl.java
@@ -37,6 +37,9 @@ public class ModelCatalogImpl extends
BaseCatalog<ModelCatalogImpl> {
private static final ModelPropertiesMetadata MODEL_PROPERTIES_META =
new ModelPropertiesMetadata();
+ private static final ModelVersionPropertiesMetadata
MODEL_VERSION_PROPERTIES_META =
+ new ModelVersionPropertiesMetadata();
+
@Override
public String shortName() {
return "model";
@@ -63,6 +66,11 @@ public class ModelCatalogImpl extends
BaseCatalog<ModelCatalogImpl> {
return MODEL_PROPERTIES_META;
}
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata() throws
UnsupportedOperationException {
+ return MODEL_VERSION_PROPERTIES_META;
+ }
+
@Override
protected Capability newCapability() {
return new ModelCatalogCapability();
diff --git
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
index 67bd58e76f..0ae316f0b7 100644
---
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
+++
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
@@ -18,15 +18,28 @@
*/
package org.apache.gravitino.catalog.model;
-import java.util.Collections;
+import static
org.apache.gravitino.model.ModelVersion.PROPERTY_DEFAULT_URI_NAME;
+
+import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.apache.gravitino.connector.BasePropertiesMetadata;
import org.apache.gravitino.connector.PropertyEntry;
public class ModelPropertiesMetadata extends BasePropertiesMetadata {
+ private static final Map<String, PropertyEntry<?>> MODEL_PROPERTY_ENTRIES =
+ ImmutableMap.<String, PropertyEntry<?>>builder()
+ .put(
+ PROPERTY_DEFAULT_URI_NAME,
+ PropertyEntry.stringOptionalPropertyEntry(
+ PROPERTY_DEFAULT_URI_NAME,
+ "The default URI name for the versions of the model",
+ false /* immutable */,
+ null,
+ false /* hidden */))
+ .build();
@Override
protected Map<String, PropertyEntry<?>> specificPropertyEntries() {
- return Collections.emptyMap();
+ return MODEL_PROPERTY_ENTRIES;
}
}
diff --git
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelVersionPropertiesMetadata.java
similarity index 59%
copy from
catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
copy to
catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelVersionPropertiesMetadata.java
index 67bd58e76f..ec31af59e3 100644
---
a/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelPropertiesMetadata.java
+++
b/catalogs/catalog-model/src/main/java/org/apache/gravitino/catalog/model/ModelVersionPropertiesMetadata.java
@@ -18,15 +18,28 @@
*/
package org.apache.gravitino.catalog.model;
-import java.util.Collections;
+import static
org.apache.gravitino.model.ModelVersion.PROPERTY_DEFAULT_URI_NAME;
+
+import com.google.common.collect.ImmutableMap;
import java.util.Map;
import org.apache.gravitino.connector.BasePropertiesMetadata;
import org.apache.gravitino.connector.PropertyEntry;
-public class ModelPropertiesMetadata extends BasePropertiesMetadata {
+public class ModelVersionPropertiesMetadata extends BasePropertiesMetadata {
+ private static final Map<String, PropertyEntry<?>>
MODEL_VERSION_PROPERTY_ENTRIES =
+ ImmutableMap.<String, PropertyEntry<?>>builder()
+ .put(
+ PROPERTY_DEFAULT_URI_NAME,
+ PropertyEntry.stringOptionalPropertyEntry(
+ PROPERTY_DEFAULT_URI_NAME,
+ "The default URI name for the model version",
+ false /* immutable */,
+ null,
+ false /* hidden */))
+ .build();
@Override
protected Map<String, PropertyEntry<?>> specificPropertyEntries() {
- return Collections.emptyMap();
+ return MODEL_VERSION_PROPERTY_ENTRIES;
}
}
diff --git a/clients/client-python/gravitino/api/model/model_version.py
b/clients/client-python/gravitino/api/model/model_version.py
index cdf8f05bd5..f1737cd2e9 100644
--- a/clients/client-python/gravitino/api/model/model_version.py
+++ b/clients/client-python/gravitino/api/model/model_version.py
@@ -28,6 +28,12 @@ class ModelVersion(Auditable):
registered model.
"""
+ PROPERTY_DEFAULT_URI_NAME = "default-uri-name"
+ """The property name for the default URI name of the model version."""
+
+ URI_NAME_UNKNOWN = "unknown"
+ """The reserved URI name to indicate the URI name is unknown."""
+
@abstractmethod
def version(self) -> int:
"""
@@ -63,15 +69,28 @@ class ModelVersion(Auditable):
"""
pass
- @abstractmethod
def uri(self) -> str:
"""
- The URI of the model artifact. The URI is the location of the model
artifact. The URI can be a
+ The unnamed URI of the model artifact. The URI is the location of the
model artifact. The URI can be a
file path or a remote URI.
Returns:
The URI of the model artifact.
"""
+ return self.uris().get(self.URI_NAME_UNKNOWN)
+
+ @abstractmethod
+ def uris(self) -> Dict[str, str]:
+ """
+ The name and corresponding URI of the model artifact. The key is the
name of the URI, and the
+ value is the location of the model artifact, which can be a file path
or a remote URI.
+
+ The "unknown" URI name is reserved for the compatibility with single
URI.
+
+ Returns:
+ The URIs of the model version, the key is the name of the URI and
the value is the URI of
+ the model artifact.
+ """
pass
def properties(self) -> Dict[str, str]:
diff --git a/clients/client-python/gravitino/client/generic_model_catalog.py
b/clients/client-python/gravitino/client/generic_model_catalog.py
index 34074284dc..0d2d4c8f39 100644
--- a/clients/client-python/gravitino/client/generic_model_catalog.py
+++ b/clients/client-python/gravitino/client/generic_model_catalog.py
@@ -465,6 +465,72 @@ class GenericModelCatalog(BaseSchemaCatalog):
base_resp = BaseResponse.from_json(resp.body, infer_missing=True)
base_resp.validate()
+ def link_model_version_with_multiple_uris(
+ self,
+ model_ident: NameIdentifier,
+ uris: Dict[str, str],
+ aliases: List[str],
+ comment: str,
+ properties: Dict[str, str],
+ ) -> None:
+ """Link a new model version to the registered model object. The new
model version will be
+ added to the model object. If the model object does not exist, it will
throw an
+ exception. If the version alias already exists in the model, it will
throw an exception.
+
+ Args:
+ model_ident: The identifier of the model.
+ uris: The URIs and their names of the model version.
+ aliases: The aliases of the model version. The aliases of the
model version. The
+ aliases should be unique in this model, otherwise the
+ ModelVersionAliasesAlreadyExistException will be thrown. The
aliases are optional and
+ can be empty.
+ comment: The comment of the model version.
+ properties: The properties of the model version.
+
+ Raises:
+ NoSuchModelException: If the model does not exist.
+ ModelVersionAliasesAlreadyExistException: If the aliases of the
model version already exist.
+ """
+ raise NotImplementedError("Not supported yet")
+
+ def get_model_version_uri(
+ self, model_ident: NameIdentifier, version: int, uri_name: str = None
+ ):
+ """Get the URI of the model artifact with a specified version number.
+
+ Args:
+ model_ident: The identifier of the model.
+ version: The version of the model.
+ uri_name: The name of the URI. If None, the default URI will be
used.
+
+ Raises:
+ NoSuchModelVersionException: If the model version does not exist.
+ NoSuchModelVersionURINameException: If the uri name does not exist.
+
+ Returns:
+ The URI of the model version.
+ """
+ raise NotImplementedError("Not supported yet")
+
+ def get_model_version_uri_by_alias(
+ self, model_ident: NameIdentifier, alias: str, uri_name: str = None
+ ):
+ """Get the URI of the model artifact with a specified version alias.
+
+ Args:
+ model_ident: The identifier of the model.
+ alias: The alias of the model version.
+ uri_name: The name of the URI. If None, the default URI will be
used.
+
+ Raises:
+ NoSuchModelVersionException: If the model version does not exist.
+ NoSuchModelVersionURINameException: If the uri name does not exist.
+
+ Returns:
+ The URI of the model version.
+ """
+ raise NotImplementedError("Not supported yet")
+
def delete_model_version(self, model_ident: NameIdentifier, version: int)
-> bool:
"""Delete the model version from the catalog. If the model version
does not exist, return false.
If the model version is successfully deleted, return true.
@@ -546,6 +612,40 @@ class GenericModelCatalog(BaseSchemaCatalog):
self.link_model_version(ident, uri, aliases, comment, properties)
return model
+ def register_model_version_with_multiple_uris(
+ self,
+ ident: NameIdentifier,
+ uris: Dict[str, str],
+ aliases: List[str],
+ comment: str,
+ properties: Dict[str, str],
+ ) -> Model:
+ """Register a model in the catalog if the model is not existed,
otherwise the
+ ModelAlreadyExistsException will be thrown. The Model object will be
created when the
+ model is registered, in the meantime, the model version (version 0)
will also be created and
+ linked to the registered model. Register a model in the catalog and
link a new model
+ version to the registered model.
+
+ Args:
+ ident: The identifier of the model.
+ uris: The URIs and their names of the model version.
+ aliases: The aliases of the model version.
+ comment: The comment of the model.
+ properties: The properties of the model.
+
+ Raises:
+ ModelAlreadyExistsException: If the model already exists.
+ ModelVersionAliasesAlreadyExistException: If the aliases of the
model version already exist.
+
+ Returns:
+ The registered model object.
+ """
+ model = self.register_model(ident, comment, properties)
+ self.link_model_version_with_multiple_uris(
+ ident, uris, aliases, comment, properties
+ )
+ return model
+
@staticmethod
def to_model_update_request(change: ModelChange):
if isinstance(change, ModelChange.RenameModel):
diff --git a/clients/client-python/gravitino/client/generic_model_version.py
b/clients/client-python/gravitino/client/generic_model_version.py
index 3cd5003977..0c13f53668 100644
--- a/clients/client-python/gravitino/client/generic_model_version.py
+++ b/clients/client-python/gravitino/client/generic_model_version.py
@@ -40,6 +40,9 @@ class GenericModelVersion(ModelVersion):
def uri(self) -> str:
return self._model_version_dto.uri()
+ def uris(self) -> Dict[str, str]:
+ return self._model_version_dto.uris()
+
def properties(self) -> Dict[str, str]:
return self._model_version_dto.properties()
diff --git a/clients/client-python/gravitino/dto/model_version_dto.py
b/clients/client-python/gravitino/dto/model_version_dto.py
index 2b287069e7..939eb2e347 100644
--- a/clients/client-python/gravitino/dto/model_version_dto.py
+++ b/clients/client-python/gravitino/dto/model_version_dto.py
@@ -49,6 +49,9 @@ class ModelVersionDTO(ModelVersion, DataClassJsonMixin):
def uri(self) -> str:
return self._uri
+ def uris(self) -> Dict[str, str]:
+ raise NotImplementedError("Not supported yet")
+
def properties(self) -> Optional[Dict[str, str]]:
return self._properties
diff --git a/clients/client-python/gravitino/exceptions/base.py
b/clients/client-python/gravitino/exceptions/base.py
index fed9585659..505655d869 100644
--- a/clients/client-python/gravitino/exceptions/base.py
+++ b/clients/client-python/gravitino/exceptions/base.py
@@ -85,6 +85,10 @@ class NoSuchModelVersionException(NotFoundException):
"""An exception thrown when a model version is not found."""
+class NoSuchModelVersionURINameException(NotFoundException):
+ """An exception thrown when a URI name of a model version is not found."""
+
+
class AlreadyExistsException(GravitinoRuntimeException):
"""Base exception thrown when an entity or resource already exists."""
diff --git
a/clients/client-python/gravitino/exceptions/handlers/model_error_handler.py
b/clients/client-python/gravitino/exceptions/handlers/model_error_handler.py
index eec52d19d5..a611a76725 100644
--- a/clients/client-python/gravitino/exceptions/handlers/model_error_handler.py
+++ b/clients/client-python/gravitino/exceptions/handlers/model_error_handler.py
@@ -20,6 +20,7 @@ from gravitino.exceptions.base import (
NoSuchSchemaException,
NoSuchModelException,
NoSuchModelVersionException,
+ NoSuchModelVersionURINameException,
NotFoundException,
ModelAlreadyExistsException,
ModelVersionAliasesAlreadyExistException,
@@ -44,6 +45,8 @@ class ModelErrorHandler(RestErrorHandler):
raise NoSuchModelException(error_message)
if exception_type == NoSuchModelVersionException.__name__:
raise NoSuchModelVersionException(error_message)
+ if exception_type == NoSuchModelVersionURINameException.__name__:
+ raise NoSuchModelVersionURINameException(error_message)
raise NotFoundException(error_message)
diff --git
a/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
b/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
index 4f62c824de..b2de2b20c1 100644
---
a/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
+++
b/core/src/main/java/org/apache/gravitino/catalog/ModelOperationDispatcher.java
@@ -23,12 +23,14 @@ import static
org.apache.gravitino.utils.NameIdentifierUtil.getCatalogIdentifier
import java.util.Arrays;
import java.util.Map;
+import java.util.function.Function;
import java.util.function.Supplier;
import org.apache.gravitino.EntityStore;
import org.apache.gravitino.NameIdentifier;
import org.apache.gravitino.Namespace;
import org.apache.gravitino.StringIdentifier;
import org.apache.gravitino.connector.HasPropertyMetadata;
+import org.apache.gravitino.connector.PropertiesMetadata;
import org.apache.gravitino.exceptions.ModelAlreadyExistsException;
import
org.apache.gravitino.exceptions.ModelVersionAliasesAlreadyExistException;
import org.apache.gravitino.exceptions.NoSuchModelException;
@@ -86,7 +88,9 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
public Model registerModel(NameIdentifier ident, String comment, Map<String,
String> properties)
throws NoSuchModelException, ModelAlreadyExistsException {
NameIdentifier catalogIdent = getCatalogIdentifier(ident);
- Map<String, String> updatedProperties =
checkAndUpdateProperties(catalogIdent, properties);
+ Map<String, String> updatedProperties =
+ checkAndUpdateProperties(
+ catalogIdent, properties,
HasPropertyMetadata::modelPropertiesMetadata);
Model registeredModel =
TreeLockUtils.doWithTreeLock(
@@ -187,7 +191,9 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
Map<String, String> properties)
throws NoSuchModelException, ModelVersionAliasesAlreadyExistException {
NameIdentifier catalogIdent = getCatalogIdentifier(ident);
- Map<String, String> updatedProperties =
checkAndUpdateProperties(catalogIdent, properties);
+ Map<String, String> updatedProperties =
+ checkAndUpdateProperties(
+ catalogIdent, properties,
HasPropertyMetadata::modelVersionPropertiesMetadata);
TreeLockUtils.doWithTreeLock(
ident,
@@ -260,7 +266,7 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
public ModelVersion alterModelVersion(
NameIdentifier ident, int version, ModelVersionChange... changes)
throws NoSuchModelVersionException, IllegalArgumentException {
- validateAlterProperties(ident,
HasPropertyMetadata::modelPropertiesMetadata, changes);
+ validateAlterProperties(ident,
HasPropertyMetadata::modelVersionPropertiesMetadata, changes);
return executeAlterModelVersion(ident, f -> f.alterModelVersion(ident,
version, changes));
}
@@ -269,7 +275,7 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
public ModelVersion alterModelVersion(
NameIdentifier ident, String alias, ModelVersionChange... changes)
throws NoSuchModelException, IllegalArgumentException {
- validateAlterProperties(ident,
HasPropertyMetadata::modelPropertiesMetadata, changes);
+ validateAlterProperties(ident,
HasPropertyMetadata::modelVersionPropertiesMetadata, changes);
return executeAlterModelVersion(ident, f -> f.alterModelVersion(ident,
alias, changes));
}
@@ -292,7 +298,7 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
.withHiddenProperties(
getHiddenPropertyNames(
catalogIdent,
- HasPropertyMetadata::modelPropertiesMetadata,
+ HasPropertyMetadata::modelVersionPropertiesMetadata,
alteredModelVersion.properties()));
}
@@ -305,7 +311,7 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
.withHiddenProperties(
getHiddenPropertyNames(
catalogIdent,
- HasPropertyMetadata::modelPropertiesMetadata,
+ HasPropertyMetadata::modelVersionPropertiesMetadata,
modelVersion.properties()));
}
@@ -320,13 +326,15 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
.withHiddenProperties(
getHiddenPropertyNames(
catalogIdent,
- HasPropertyMetadata::modelPropertiesMetadata,
+
HasPropertyMetadata::modelVersionPropertiesMetadata,
v.properties())))
.toArray(ModelVersion[]::new);
}
private Map<String, String> checkAndUpdateProperties(
- NameIdentifier catalogIdent, Map<String, String> properties) {
+ NameIdentifier catalogIdent,
+ Map<String, String> properties,
+ Function<HasPropertyMetadata, PropertiesMetadata>
propertiesMetadataProvider) {
TreeLockUtils.doWithTreeLock(
catalogIdent,
LockType.READ,
@@ -336,7 +344,8 @@ public class ModelOperationDispatcher extends
OperationDispatcher implements Mod
c ->
c.doWithPropertiesMeta(
p -> {
-
validatePropertyForCreate(p.modelPropertiesMetadata(), properties);
+ validatePropertyForCreate(
+ propertiesMetadataProvider.apply(p), properties);
return null;
}),
IllegalArgumentException.class));
diff --git a/core/src/main/java/org/apache/gravitino/connector/BaseCatalog.java
b/core/src/main/java/org/apache/gravitino/connector/BaseCatalog.java
index 539a19e331..6c749f903f 100644
--- a/core/src/main/java/org/apache/gravitino/connector/BaseCatalog.java
+++ b/core/src/main/java/org/apache/gravitino/connector/BaseCatalog.java
@@ -155,6 +155,12 @@ public abstract class BaseCatalog<T extends BaseCatalog>
"The catalog does not support model properties metadata");
}
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata() throws
UnsupportedOperationException {
+ throw new UnsupportedOperationException(
+ "The catalog does not support model version properties metadata");
+ }
+
/**
* Retrieves the CatalogOperations instance associated with this catalog.
Lazily initializes the
* instance if not already created.
diff --git
a/core/src/main/java/org/apache/gravitino/connector/HasPropertyMetadata.java
b/core/src/main/java/org/apache/gravitino/connector/HasPropertyMetadata.java
index e8e02b6ffa..c0fdc8c355 100644
--- a/core/src/main/java/org/apache/gravitino/connector/HasPropertyMetadata.java
+++ b/core/src/main/java/org/apache/gravitino/connector/HasPropertyMetadata.java
@@ -71,4 +71,12 @@ public interface HasPropertyMetadata {
* @throws UnsupportedOperationException if the entity does not support
model properties.
*/
PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException;
+
+ /**
+ * Returns the model version property metadata.
+ *
+ * @return The model version property metadata.
+ * @throws UnsupportedOperationException if the entity does not support
model version properties.
+ */
+ PropertiesMetadata modelVersionPropertiesMetadata() throws
UnsupportedOperationException;
}
diff --git a/core/src/test/java/org/apache/gravitino/TestCatalog.java
b/core/src/test/java/org/apache/gravitino/TestCatalog.java
index fe353b94e9..fbea6b5e59 100644
--- a/core/src/test/java/org/apache/gravitino/TestCatalog.java
+++ b/core/src/test/java/org/apache/gravitino/TestCatalog.java
@@ -191,4 +191,9 @@ public class TestCatalog extends BaseCatalog<TestCatalog> {
public PropertiesMetadata modelPropertiesMetadata() throws
UnsupportedOperationException {
return BASE_PROPERTIES_METADATA;
}
+
+ @Override
+ public PropertiesMetadata modelVersionPropertiesMetadata() throws
UnsupportedOperationException {
+ return BASE_PROPERTIES_METADATA;
+ }
}