This is an automated email from the ASF dual-hosted git repository.
fanng 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 c9c9a99dff [#6076] improve(core): Support model pre event to Gravitino
server (#6250)
c9c9a99dff is described below
commit c9c9a99dff6d5f90a08e1f1624554f79e8d531aa
Author: Lord of Abyss <[email protected]>
AuthorDate: Tue Mar 11 13:04:55 2025 +0800
[#6076] improve(core): Support model pre event to Gravitino server (#6250)
### What changes were proposed in this pull request?
Support model pre event to Gravitino server, based on #6129 , Both
synchronize Dispatcher changes with each other
https://docs.google.com/document/d/1_aVCd_tKiEebpzp9tg07Lzdk1j6EalNn8YOIdRn-3z4/edit?tab=t.0#heading=h.k85t4bueowc5
#### PreEvent
| PreEvent | OperationType | ModelCatalog |
| --- | --- | --- |
| `RegisterModelPreEvent` | `REGISTER_MODEL` | `registerModel` |
| `GetModelPreEvent` | `LOAD_MODEL` | `getModel` |
| `DeleteModelEvent` | `Delete_MODEL` | `deleteModel` |
| `ListModelPreEvent` | `LIST_MODEL` | `listModels` |
| `LinkModelVersionPreEvent` | `LINK_MODEL_VERSION` | `linkModelVersion`
|
| `GetModelVersionPreEvent` | `GET_MODEL_VERSION` | `getModelVersion` |
| `DeleteModelVersionPreEvent` | `Delete_MODEL_VERSION` |
`deleteModelVersion` |
| `ListModelVersionsPreEvent` | `LIST_MODEL_VERSIONS` |
`listModelVersions` |
#### ModelEventDispatcher

### Why are the changes needed?
Fix: #6076
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
#### Model Event
1. `testRegisterModelEvent`
2. `testGetModelEvent`
3. `testDeleteExistsModelEvent`
4. `testDeleteNotExistsModelEvent`
5. `testListModelEvent`
#### Model Version Event
1. `testLinkModelVersionEvent`
2. `testGetModelVersionEventViaVersion`
3. `testGetModelVersionEventViaAlias`
4. `testDeleteModelVersionEventViaVersion`
5. `testDeleteModelVersionEventViaAlias`
6. `testDeleteModelVersionEventViaVersionNotExists`
7. `testListModelVersionsEvent`
---------
Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: luoxin <[email protected]>
Co-authored-by: luoxin5 <[email protected]>
Co-authored-by: Yuhui <[email protected]>
Co-authored-by: Qi Yu <[email protected]>
Co-authored-by: YangJie <[email protected]>
Co-authored-by: this-user <[email protected]>
Co-authored-by: Qian Xia <[email protected]>
Co-authored-by: vitamin43 <[email protected]>
Co-authored-by: roryqi <[email protected]>
Co-authored-by: Pranay Kumar Karvi <[email protected]>
Co-authored-by: AndreVale69 <[email protected]>
Co-authored-by: Abdullah Javed
<[email protected]>
Co-authored-by: Brijesh Thummar <[email protected]>
Co-authored-by: Zhengke Zhou <[email protected]>
Co-authored-by: Justin Mclean <[email protected]>
Co-authored-by: Jerry Shao <[email protected]>
Co-authored-by: Kang <[email protected]>
Co-authored-by: dependabot[bot]
<49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: FANNG <[email protected]>
Co-authored-by: Eric Chang <[email protected]>
Co-authored-by: Tianhang <[email protected]>
Co-authored-by: teo <[email protected]>
Co-authored-by: teo <[email protected]>
---
.../gravitino/listener/ModelEventDispatcher.java | 270 +++++++++++++
.../listener/api/event/DeleteModelPreEvent.java | 48 +++
.../api/event/DeleteModelVersionPreEvent.java | 88 +++++
.../listener/api/event/GetModelPreEvent.java | 47 +++
.../api/event/GetModelVersionPreEvent.java | 78 ++++
.../api/event/LinkModelVersionPreEvent.java | 63 +++
.../listener/api/event/ListModelPreEvent.java | 60 +++
.../api/event/ListModelVersionPreEvent.java | 41 ++
.../listener/api/event/ModelPreEvent.java | 37 ++
.../listener/api/event/OperationType.java | 13 +
.../api/event/RegisterAndLinkModelPreEvent.java | 77 ++++
.../listener/api/event/RegisterModelPreEvent.java | 62 +++
.../gravitino/listener/api/info/ModelInfo.java | 118 ++++++
.../listener/api/info/ModelVersionInfo.java | 126 ++++++
.../listener/api/event/TestModelEvent.java | 427 +++++++++++++++++++++
docs/gravitino-server-config.md | 19 +-
16 files changed, 1565 insertions(+), 9 deletions(-)
diff --git
a/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
b/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
new file mode 100644
index 0000000000..9ffd7e8ae6
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/listener/ModelEventDispatcher.java
@@ -0,0 +1,270 @@
+/*
+ * 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.listener;
+
+import java.util.Map;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.catalog.ModelDispatcher;
+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.NoSuchSchemaException;
+import org.apache.gravitino.listener.api.event.DeleteModelPreEvent;
+import org.apache.gravitino.listener.api.event.DeleteModelVersionPreEvent;
+import org.apache.gravitino.listener.api.event.GetModelPreEvent;
+import org.apache.gravitino.listener.api.event.GetModelVersionPreEvent;
+import org.apache.gravitino.listener.api.event.LinkModelVersionPreEvent;
+import org.apache.gravitino.listener.api.event.ListModelPreEvent;
+import org.apache.gravitino.listener.api.event.ListModelVersionPreEvent;
+import org.apache.gravitino.listener.api.event.RegisterAndLinkModelPreEvent;
+import org.apache.gravitino.listener.api.event.RegisterModelPreEvent;
+import org.apache.gravitino.listener.api.info.ModelInfo;
+import org.apache.gravitino.listener.api.info.ModelVersionInfo;
+import org.apache.gravitino.model.Model;
+import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.utils.PrincipalUtils;
+
+/**
+ * {@code ModelEventDispatcher} is a decorator for {@link ModelDispatcher}
that not only delegates
+ * model operations to the underlying catalog dispatcher but also dispatches
corresponding events to
+ * an {@link org.apache.gravitino.listener.EventBus} after each operation is
completed. This allows
+ * for event-driven workflows or monitoring of model operations.
+ */
+public class ModelEventDispatcher implements ModelDispatcher {
+ private final EventBus eventBus;
+ private final ModelDispatcher dispatcher;
+
+ /**
+ * Constructs a {@link ModelEventDispatcher} with a specified EventBus and
{@link
+ * ModelDispatcher}.
+ *
+ * @param eventBus The EventBus to which events will be dispatched.
+ * @param dispatcher The underlying {@link ModelDispatcher} that will
perform the actual model
+ * operations.
+ */
+ public ModelEventDispatcher(EventBus eventBus, ModelDispatcher dispatcher) {
+ this.eventBus = eventBus;
+ this.dispatcher = dispatcher;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Model registerModel(NameIdentifier ident, String comment, Map<String,
String> properties)
+ throws NoSuchSchemaException, ModelAlreadyExistsException {
+ ModelInfo registerRequest = new ModelInfo(ident.name(), properties,
comment);
+ eventBus.dispatchEvent(
+ new RegisterModelPreEvent(PrincipalUtils.getCurrentUserName(), ident,
registerRequest));
+ try {
+ Model model = dispatcher.registerModel(ident, comment, properties);
+ // TODO: ModelEvent
+ return model;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Model registerModel(
+ NameIdentifier ident,
+ String uri,
+ String[] aliases,
+ String comment,
+ Map<String, String> properties)
+ throws NoSuchSchemaException, ModelAlreadyExistsException,
+ ModelVersionAliasesAlreadyExistException {
+ ModelInfo registerModelRequest = new ModelInfo(ident.name(), properties,
comment);
+ ModelVersionInfo linkModelVersionRequest =
+ new ModelVersionInfo(uri, comment, properties, aliases);
+
+ RegisterAndLinkModelPreEvent registerAndLinkModelPreEvent =
+ new RegisterAndLinkModelPreEvent(
+ PrincipalUtils.getCurrentUserName(),
+ ident,
+ registerModelRequest,
+ linkModelVersionRequest);
+ eventBus.dispatchEvent(registerAndLinkModelPreEvent);
+ try {
+ // TODO: ModelEvent
+ return dispatcher.registerModel(ident, uri, aliases, comment,
properties);
+ } catch (Exception e) {
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public Model getModel(NameIdentifier ident) throws NoSuchModelException {
+ eventBus.dispatchEvent(new
GetModelPreEvent(PrincipalUtils.getCurrentUserName(), ident));
+ try {
+ Model model = dispatcher.getModel(ident);
+ // TODO: ModelEvent
+ return model;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean deleteModel(NameIdentifier ident) {
+ eventBus.dispatchEvent(new
DeleteModelPreEvent(PrincipalUtils.getCurrentUserName(), ident));
+ try {
+ // TODO: ModelEvent
+ return dispatcher.deleteModel(ident);
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public NameIdentifier[] listModels(Namespace namespace) throws
NoSuchSchemaException {
+ eventBus.dispatchEvent(new
ListModelPreEvent(PrincipalUtils.getCurrentUserName(), namespace));
+ try {
+ NameIdentifier[] models = dispatcher.listModels(namespace);
+ // TODO: ModelEvent
+ return models;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void linkModelVersion(
+ NameIdentifier ident,
+ String uri,
+ String[] aliases,
+ String comment,
+ Map<String, String> properties)
+ throws NoSuchModelException, ModelVersionAliasesAlreadyExistException {
+ ModelVersionInfo linkModelRequest = new ModelVersionInfo(uri, comment,
properties, aliases);
+ eventBus.dispatchEvent(
+ new LinkModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident, linkModelRequest));
+ try {
+ dispatcher.linkModelVersion(ident, uri, aliases, comment, properties);
+ // TODO: ModelEvent
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion getModelVersion(NameIdentifier ident, int version)
+ throws NoSuchModelVersionException {
+ eventBus.dispatchEvent(
+ new GetModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident, null, version));
+ try {
+ // TODO: ModelEvent
+ return dispatcher.getModelVersion(ident, version);
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ModelVersion getModelVersion(NameIdentifier ident, String alias)
+ throws NoSuchModelVersionException {
+ eventBus.dispatchEvent(
+ new GetModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident, alias, null));
+ try {
+ ModelVersion modelVersion = dispatcher.getModelVersion(ident, alias);
+ // TODO: ModelEvent
+ return modelVersion;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean deleteModelVersion(NameIdentifier ident, int version) {
+ eventBus.dispatchEvent(
+ new DeleteModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident, null, version));
+ try {
+ boolean isExists = dispatcher.deleteModelVersion(ident, version);
+ // TODO: ModelEvent
+ return isExists;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean deleteModelVersion(NameIdentifier ident, String alias) {
+ eventBus.dispatchEvent(
+ new DeleteModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident, alias, null));
+ try {
+ boolean isExists = dispatcher.deleteModelVersion(ident, alias);
+ // TODO: ModelEvent
+ return isExists;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public int[] listModelVersions(NameIdentifier ident) throws
NoSuchModelException {
+ eventBus.dispatchEvent(
+ new ListModelVersionPreEvent(PrincipalUtils.getCurrentUserName(),
ident));
+ try {
+ int[] versions = dispatcher.listModelVersions(ident);
+ // TODO: ModelEvent
+ return versions;
+ } catch (Exception e) {
+ // TODO: failureEvent
+ throw e;
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean modelExists(NameIdentifier ident) {
+ return dispatcher.modelExists(ident);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean modelVersionExists(NameIdentifier ident, int version) {
+ return dispatcher.modelVersionExists(ident, version);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public boolean modelVersionExists(NameIdentifier ident, String alias) {
+ return dispatcher.modelVersionExists(ident, alias);
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelPreEvent.java
new file mode 100644
index 0000000000..2e8c452e22
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelPreEvent.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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before deleting a model. */
+@DeveloperApi
+public class DeleteModelPreEvent extends ModelPreEvent {
+
+ /**
+ * Create a new {@link DeleteModelPreEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param identifier the identifier of the model being operated on.
+ */
+ public DeleteModelPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.DELETE_MODEL;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelVersionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelVersionPreEvent.java
new file mode 100644
index 0000000000..0b70db145d
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/DeleteModelVersionPreEvent.java
@@ -0,0 +1,88 @@
+/*
+ * 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.listener.api.event;
+
+import java.util.Optional;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before deleting a model version. */
+@DeveloperApi
+public class DeleteModelVersionPreEvent extends ModelPreEvent {
+ private final Optional<String> alias;
+ private final Optional<Integer> version;
+
+ /**
+ * Create a new {@link DeleteModelVersionPreEvent} instance.
+ *
+ * @param user The username of the individual who initiated the model
version linking.
+ * @param identifier The unique identifier of the model that was linked.
+ */
+ public DeleteModelVersionPreEvent(String user, NameIdentifier identifier) {
+ this(user, identifier, null, null);
+ }
+
+ /**
+ * Create a new {@link DeleteModelVersionPreEvent} instance. only one of
alias or version are
+ * valid.
+ *
+ * @param user The username of the individual who initiated the model
version deleted.
+ * @param identifier The unique identifier of the model that was deleted.
+ * @param alias The alias of the model version to be deleted.
+ * @param version The version of the model version to be deleted.
+ */
+ public DeleteModelVersionPreEvent(
+ String user, NameIdentifier identifier, String alias, Integer version) {
+ super(user, identifier);
+
+ this.alias = Optional.ofNullable(alias);
+ this.version = Optional.ofNullable(version);
+ }
+
+ /**
+ * Returns the alias of the model version to be deleted.
+ *
+ * @return A {@link Optional} instance containing the alias if it was
provided, or an empty {@link
+ * Optional} otherwise.
+ */
+ public Optional<String> alias() {
+ return alias;
+ }
+
+ /**
+ * Returns the version of the model version to be deleted.
+ *
+ * @return A {@link Optional} instance containing the version if it was
provided, or an empty
+ * {@link Optional} otherwise.
+ */
+ public Optional<Integer> version() {
+ return version;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.DELETE_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelPreEvent.java
new file mode 100644
index 0000000000..1161a15688
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelPreEvent.java
@@ -0,0 +1,47 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before getting a model. */
+@DeveloperApi
+public class GetModelPreEvent extends ModelPreEvent {
+ /**
+ * Create a new {@link GetModelPreEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param identifier the identifier of the model being operated on.
+ */
+ public GetModelPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.GET_MODEL;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelVersionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelVersionPreEvent.java
new file mode 100644
index 0000000000..3b671d8e31
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/GetModelVersionPreEvent.java
@@ -0,0 +1,78 @@
+/*
+ * 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.listener.api.event;
+
+import java.util.Optional;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before getting the version of a model. */
+@DeveloperApi
+public class GetModelVersionPreEvent extends ModelPreEvent {
+ private final Optional<String> alias;
+ private final Optional<Integer> version;
+
+ /**
+ * Create a new {@link GetModelVersionPreEvent} instance with optional alias
and version
+ * arguments. only one of alias or version are valid.
+ *
+ * @param user The username of the individual who initiated the model
version to get.
+ * @param identifier The unique identifier of the model that was getting the
version.
+ * @param alias The alias of the model version to get.
+ * @param version The version of the model version to get.
+ */
+ public GetModelVersionPreEvent(
+ String user, NameIdentifier identifier, String alias, Integer version) {
+ super(user, identifier);
+
+ this.alias = Optional.ofNullable(alias);
+ this.version = Optional.ofNullable(version);
+ }
+
+ /**
+ * Returns the alias of the model version to be deleted.
+ *
+ * @return A {@link Optional} instance containing the alias if it was
provided, or an empty {@link
+ * Optional} otherwise.
+ */
+ public Optional<String> alias() {
+ return alias;
+ }
+
+ /**
+ * Returns the version of the model version to be deleted.
+ *
+ * @return A {@link Optional} instance containing the version if it was
provided, or an empty
+ * {@link Optional} otherwise.
+ */
+ public Optional<Integer> version() {
+ return version;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.GET_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/LinkModelVersionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/LinkModelVersionPreEvent.java
new file mode 100644
index 0000000000..7f05aa0a34
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/LinkModelVersionPreEvent.java
@@ -0,0 +1,63 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.ModelVersionInfo;
+
+/** Represents an event triggered before the linking of a model version. */
+@DeveloperApi
+public class LinkModelVersionPreEvent extends ModelPreEvent {
+ private final ModelVersionInfo linkModelVersionRequest;
+
+ /**
+ * Create a new {@link LinkModelVersionPreEvent} instance.
+ *
+ * @param user The username of the individual who initiated the model
version linking.
+ * @param identifier The unique identifier of the model that was linked.
+ * @param linkModelVersionRequest The version information of the model that
was requested to be
+ * linked.
+ */
+ public LinkModelVersionPreEvent(
+ String user, NameIdentifier identifier, ModelVersionInfo
linkModelVersionRequest) {
+ super(user, identifier);
+ this.linkModelVersionRequest = linkModelVersionRequest;
+ }
+
+ /**
+ * Retrieves the linked model version information.
+ *
+ * @return the model version information.
+ */
+ public ModelVersionInfo linkModelVersionRequest() {
+ return linkModelVersionRequest;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.LINK_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelPreEvent.java
new file mode 100644
index 0000000000..75b444b3d1
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelPreEvent.java
@@ -0,0 +1,60 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before listing of models within a namespace.
*/
+@DeveloperApi
+public class ListModelPreEvent extends ModelPreEvent {
+ private final Namespace namespace;
+
+ /**
+ * Create a new {@link ListModelPreEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param namespace the namespace to list models from.
+ */
+ public ListModelPreEvent(String user, Namespace namespace) {
+ super(user, NameIdentifier.of(namespace.levels()));
+ this.namespace = namespace;
+ }
+
+ /**
+ * Provides the namespace associated with this event.
+ *
+ * @return A {@link Namespace} instance from which models were listed.
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_MODEL;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelVersionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelVersionPreEvent.java
new file mode 100644
index 0000000000..fb18905b25
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ListModelVersionPreEvent.java
@@ -0,0 +1,41 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents an event triggered before listing model versions. */
+@DeveloperApi
+public class ListModelVersionPreEvent extends ModelPreEvent {
+ public ListModelVersionPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_MODEL_VERSIONS;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/ModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/ModelPreEvent.java
new file mode 100644
index 0000000000..11faf3deeb
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/ModelPreEvent.java
@@ -0,0 +1,37 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+
+/** Represents a pre-event for model operations. */
+@DeveloperApi
+public abstract class ModelPreEvent extends PreEvent {
+ /**
+ * Create a new {@link ModelPreEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param identifier the identifier of the model being operated on.
+ */
+ protected ModelPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
index 515e63a7c3..9ad171f10f 100644
---
a/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/OperationType.java
@@ -99,5 +99,18 @@ public enum OperationType {
RENAME_VIEW,
LIST_VIEW,
+ // Model event
+ REGISTER_MODEL,
+ DELETE_MODEL,
+ GET_MODEL,
+ LIST_MODEL,
+
+ // Model Version
+ LINK_MODEL_VERSION,
+ DELETE_MODEL_VERSION,
+ GET_MODEL_VERSION,
+ LIST_MODEL_VERSIONS,
+ REGISTER_AND_LINK_MODEL_VERSION,
+
UNKNOWN,
}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterAndLinkModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterAndLinkModelPreEvent.java
new file mode 100644
index 0000000000..afce9bda8b
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterAndLinkModelPreEvent.java
@@ -0,0 +1,77 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.listener.api.info.ModelInfo;
+import org.apache.gravitino.listener.api.info.ModelVersionInfo;
+
+/** Represents an event triggered before registering a model and linking a
model version. */
+public class RegisterAndLinkModelPreEvent extends ModelPreEvent {
+ private final ModelInfo registerModelRequest;
+ private final ModelVersionInfo linkModelVersionRequest;
+
+ /**
+ * Create a new {@code RegisterAndLinkModelEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param identifier the identifier of the model being operated on.
+ * @param registerModelRequest the model information that was requested to
be registered.
+ * @param linkModelVersionRequest The version information of the model that
was requested to be
+ * linked.
+ */
+ public RegisterAndLinkModelPreEvent(
+ String user,
+ NameIdentifier identifier,
+ ModelInfo registerModelRequest,
+ ModelVersionInfo linkModelVersionRequest) {
+ super(user, identifier);
+ this.registerModelRequest = registerModelRequest;
+ this.linkModelVersionRequest = linkModelVersionRequest;
+ }
+
+ /**
+ * Retrieves the registered model information.
+ *
+ * @return the model information.
+ */
+ public ModelInfo registerModelRequest() {
+ return registerModelRequest;
+ }
+
+ /**
+ * Retrieves the linked model version information.
+ *
+ * @return the model version information.
+ */
+ public ModelVersionInfo linkModelVersionRequest() {
+ return linkModelVersionRequest;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.REGISTER_AND_LINK_MODEL_VERSION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterModelPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterModelPreEvent.java
new file mode 100644
index 0000000000..905358c53d
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/RegisterModelPreEvent.java
@@ -0,0 +1,62 @@
+/*
+ * 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.listener.api.event;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.info.ModelInfo;
+
+/** Represents an event triggered before registering a model. */
+@DeveloperApi
+public class RegisterModelPreEvent extends ModelPreEvent {
+ private final ModelInfo registerModelRequest;
+
+ /**
+ * Create a new {@link RegisterModelPreEvent} instance.
+ *
+ * @param user the user who triggered the event.
+ * @param identifier the identifier of the model being operated on.
+ * @param registerModelRequest the model information that was requested to
be registered.
+ */
+ public RegisterModelPreEvent(
+ String user, NameIdentifier identifier, ModelInfo registerModelRequest) {
+ super(user, identifier);
+ this.registerModelRequest = registerModelRequest;
+ }
+
+ /**
+ * Retrieves the registered model information.
+ *
+ * @return the model information.
+ */
+ public ModelInfo registerModelRequest() {
+ return registerModelRequest;
+ }
+
+ /**
+ * Returns the type of operation.
+ *
+ * @return the operation type.
+ */
+ @Override
+ public OperationType operationType() {
+ return OperationType.REGISTER_MODEL;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/info/ModelInfo.java
b/core/src/main/java/org/apache/gravitino/listener/api/info/ModelInfo.java
new file mode 100644
index 0000000000..870f725277
--- /dev/null
+++ b/core/src/main/java/org/apache/gravitino/listener/api/info/ModelInfo.java
@@ -0,0 +1,118 @@
+/*
+ * 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.listener.api.info;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.gravitino.Audit;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.model.Model;
+
+/**
+ * ModelInfo exposes model information for event listener, it's supposed to be
read only. Most of
+ * the fields are shallow copied internally not deep copies for performance.
+ */
+@DeveloperApi
+public class ModelInfo {
+ private final String name;
+ private final Map<String, String> properties;
+ private final Optional<String> comment;
+ private final Optional<Audit> audit;
+ private final Optional<Integer> lastVersion;
+
+ /**
+ * Constructs model information based on a given model.
+ *
+ * @param model the model to expose information for.
+ */
+ public ModelInfo(Model model) {
+ this.name = model.name();
+ this.properties =
+ model.properties() == null ? ImmutableMap.of() :
ImmutableMap.copyOf(model.properties());
+
+ this.comment = Optional.ofNullable(model.comment());
+ this.audit = Optional.ofNullable(model.auditInfo());
+ this.lastVersion = Optional.ofNullable(model.latestVersion());
+ }
+
+ public ModelInfo(String name, Map<String, String> properties, String
comment) {
+ this(name, properties, comment, null, null);
+ }
+
+ public ModelInfo(
+ String name,
+ Map<String, String> properties,
+ String comment,
+ Audit audit,
+ Integer lastVersion) {
+ this.name = name;
+
+ this.properties = properties == null ? ImmutableMap.of() :
ImmutableMap.copyOf(properties);
+ this.comment = Optional.ofNullable(comment);
+ this.audit = Optional.ofNullable(audit);
+ this.lastVersion = Optional.ofNullable(lastVersion);
+ }
+
+ /**
+ * Returns the name of the model.
+ *
+ * @return the name of the model.
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the properties of the model.
+ *
+ * @return the properties of the model.
+ */
+ public Map<String, String> properties() {
+ return properties;
+ }
+
+ /**
+ * Returns the comment of the model.
+ *
+ * @return the comment of the model or null if not set.
+ */
+ public Optional<String> comment() {
+ return comment;
+ }
+
+ /**
+ * Returns the audit information of the model.
+ *
+ * @return the audit information of the model or null if not set.
+ */
+ public Optional<Audit> audit() {
+ return audit;
+ }
+
+ /**
+ * returns the last version of the model.
+ *
+ * @return the last version of the model, or empty if not set.
+ */
+ public Optional<Integer> lastVersion() {
+ return lastVersion;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/info/ModelVersionInfo.java
b/core/src/main/java/org/apache/gravitino/listener/api/info/ModelVersionInfo.java
new file mode 100644
index 0000000000..a9a953a86e
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/info/ModelVersionInfo.java
@@ -0,0 +1,126 @@
+/*
+ * 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.listener.api.info;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
+import java.util.Optional;
+import org.apache.gravitino.Audit;
+import org.apache.gravitino.model.ModelVersion;
+
+/**
+ * {@link ModelVersionInfo} exposes model version information for event
listener, it's supposed to
+ * be read only. Most of the fields are shallow copied internally not deep
copies for performance.
+ */
+public class ModelVersionInfo {
+ private final String uri;
+ private final Map<String, String> properties;
+
+ private final Optional<String[]> aliases;
+ private final Optional<String> comment;
+ private final Optional<Audit> auditInfo;
+
+ /**
+ * Constructs model version information based on a given {@link
ModelVersion}.
+ *
+ * @param modelVersion the model version to expose information for.
+ */
+ public ModelVersionInfo(ModelVersion modelVersion) {
+ this(
+ modelVersion.uri(),
+ modelVersion.comment(),
+ modelVersion.properties(),
+ modelVersion.aliases(),
+ modelVersion.auditInfo());
+ }
+
+ public ModelVersionInfo(
+ String uri, String comment, Map<String, String> properties, String[]
aliases) {
+ this(uri, comment, properties, aliases, null);
+ }
+
+ /**
+ * Constructs model version information based on a given arguments.
+ *
+ * @param uri
+ * @param aliases
+ * @param comment
+ * @param properties
+ */
+ public ModelVersionInfo(
+ String uri,
+ String comment,
+ Map<String, String> properties,
+ String[] aliases,
+ Audit auditInfo) {
+ this.uri = uri;
+
+ this.properties = properties == null ? ImmutableMap.of() :
ImmutableMap.copyOf(properties);
+ this.comment = Optional.ofNullable(comment);
+ this.auditInfo = Optional.ofNullable(auditInfo);
+ this.aliases = Optional.ofNullable(aliases);
+ }
+
+ /**
+ * Returns the URI of the model version.
+ *
+ * @return the URI of the model version.
+ */
+ public String uri() {
+ return uri;
+ }
+
+ /**
+ * Returns the properties associated with the model version.
+ *
+ * @return Map of table properties.
+ */
+ public Map<String, String> properties() {
+ return properties;
+ }
+
+ /**
+ * Returns the aliases of the model version.
+ *
+ * @return the aliases of the model version (a {@code Optional<String[]>}
instance) or null if not
+ * set.
+ */
+ public Optional<String[]> aliases() {
+ return aliases;
+ }
+
+ /**
+ * Returns the comment of the model version.
+ *
+ * @return the comment of the model version or null if not set.
+ */
+ public Optional<String> comment() {
+ return comment;
+ }
+
+ /**
+ * Returns the audit information of the model version.
+ *
+ * @return the audit information of the model version or null if not set.
+ */
+ public Optional<Audit> audit() {
+ return auditInfo;
+ }
+}
diff --git
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
new file mode 100644
index 0000000000..8489301435
--- /dev/null
+++
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestModelEvent.java
@@ -0,0 +1,427 @@
+/*
+ * 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.listener.api.event;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import com.google.common.collect.ImmutableMap;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.Map;
+import org.apache.gravitino.Audit;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.catalog.ModelDispatcher;
+import org.apache.gravitino.exceptions.GravitinoRuntimeException;
+import org.apache.gravitino.listener.DummyEventListener;
+import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.ModelEventDispatcher;
+import org.apache.gravitino.listener.api.info.ModelInfo;
+import org.apache.gravitino.listener.api.info.ModelVersionInfo;
+import org.apache.gravitino.model.Model;
+import org.apache.gravitino.model.ModelVersion;
+import org.apache.gravitino.utils.NameIdentifierUtil;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+
+@TestInstance(TestInstance.Lifecycle.PER_CLASS)
+public class TestModelEvent {
+ private ModelEventDispatcher dispatcher;
+ private ModelEventDispatcher failureDispatcher;
+ private DummyEventListener dummyEventListener;
+ private Model modelA;
+ private Model modelB;
+ private NameIdentifier existingIdentA;
+ private NameIdentifier existingIdentB;
+ private NameIdentifier notExistingIdent;
+ private Namespace namespace;
+ private ModelVersion firstModelVersion;
+ private ModelVersion secondModelVersion;
+
+ @BeforeAll
+ void init() {
+ this.namespace = Namespace.of("metalake", "catalog", "schema");
+ this.modelA = getMockModel("modelA", "commentA");
+ this.modelB = getMockModel("modelB", "commentB");
+ this.firstModelVersion =
+ mockModelVersion("uriA", new String[] {"aliasProduction"},
"versionInfoA");
+ this.secondModelVersion = mockModelVersion("uriB", new String[]
{"aliasTest"}, "versionInfoB");
+ System.out.println(secondModelVersion.toString());
+ this.existingIdentA = NameIdentifierUtil.ofModel("metalake", "catalog",
"schema", "modelA");
+ this.existingIdentB = NameIdentifierUtil.ofModel("metalake", "catalog",
"schema", "modelB");
+ this.notExistingIdent =
+ NameIdentifierUtil.ofModel("metalake", "catalog", "schema",
"not_exist");
+ this.dummyEventListener = new DummyEventListener();
+
+ EventBus eventBus = new
EventBus(Collections.singletonList(dummyEventListener));
+ this.dispatcher = new ModelEventDispatcher(eventBus, mockTagDispatcher());
+ this.failureDispatcher = new ModelEventDispatcher(eventBus,
mockExceptionModelDispatcher());
+ // TODO: add failure dispatcher tests.
+ System.out.println(this.failureDispatcher.toString());
+ }
+
+ @Test
+ void testModelInfo() {
+ Model mockModel = getMockModel("model", "comment");
+ ModelInfo modelInfo = new ModelInfo(mockModel);
+
+ Assertions.assertEquals("model", modelInfo.name());
+ Assertions.assertEquals(1, modelInfo.properties().size());
+ Assertions.assertEquals("#FFFFFF", modelInfo.properties().get("color"));
+
+ Assertions.assertTrue(modelInfo.comment().isPresent());
+ String comment = modelInfo.comment().get();
+ Assertions.assertEquals("comment", comment);
+
+ Assertions.assertFalse(modelInfo.audit().isPresent());
+
+ Assertions.assertTrue(modelInfo.lastVersion().isPresent());
+ int lastVersion = modelInfo.lastVersion().get();
+ Assertions.assertEquals(1, lastVersion);
+ }
+
+ @Test
+ void testModelInfoWithoutComment() {
+ Model mockModel = getMockModel("model", null);
+ ModelInfo modelInfo = new ModelInfo(mockModel);
+
+ Assertions.assertFalse(modelInfo.comment().isPresent());
+ }
+
+ @Test
+ void testModelInfoWithAudit() {
+ Model mockModel = getMockModelWithAudit("model", "comment");
+ ModelInfo modelInfo = new ModelInfo(mockModel);
+
+ Assertions.assertEquals("model", modelInfo.name());
+ Assertions.assertEquals(1, modelInfo.properties().size());
+ Assertions.assertEquals("#FFFFFF", modelInfo.properties().get("color"));
+
+ Assertions.assertTrue(modelInfo.comment().isPresent());
+ String comment = modelInfo.comment().get();
+ Assertions.assertEquals("comment", comment);
+
+ Assertions.assertTrue(modelInfo.audit().isPresent());
+ Audit audit = modelInfo.audit().get();
+ Assertions.assertEquals("demo_user", audit.creator());
+ Assertions.assertEquals(1611111111111L, audit.createTime().toEpochMilli());
+ Assertions.assertEquals("demo_user", audit.lastModifier());
+ Assertions.assertEquals(1611111111111L,
audit.lastModifiedTime().toEpochMilli());
+ }
+
+ @Test
+ void testRegisterModelEvent() {
+ dispatcher.registerModel(existingIdentA, "commentA",
ImmutableMap.of("color", "#FFFFFF"));
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(RegisterModelPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.REGISTER_MODEL,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ // validate pre-event model info
+ RegisterModelPreEvent registerModelPreEvent = (RegisterModelPreEvent)
preEvent;
+ Assertions.assertEquals(existingIdentA,
registerModelPreEvent.identifier());
+ ModelInfo modelInfoPreEvent = registerModelPreEvent.registerModelRequest();
+
+ Assertions.assertEquals("modelA", modelInfoPreEvent.name());
+ Assertions.assertEquals(ImmutableMap.of("color", "#FFFFFF"),
modelInfoPreEvent.properties());
+ Assertions.assertTrue(modelInfoPreEvent.comment().isPresent());
+ String comment = modelInfoPreEvent.comment().get();
+ Assertions.assertEquals("commentA", comment);
+ Assertions.assertFalse(modelInfoPreEvent.audit().isPresent());
+ Assertions.assertFalse(modelInfoPreEvent.lastVersion().isPresent());
+ }
+
+ @Test
+ void testRegisterAndLinkModelEvent() {
+ dispatcher.registerModel(
+ existingIdentA,
+ "uriA",
+ new String[] {"aliasProduction", "aliasTest"},
+ "commentA",
+ ImmutableMap.of("color", "#FFFFFF"));
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(RegisterAndLinkModelPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(
+ OperationType.REGISTER_AND_LINK_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ // validate pre-event model info
+ RegisterAndLinkModelPreEvent registerAndLinkModelPreEvent =
+ (RegisterAndLinkModelPreEvent) preEvent;
+ ModelInfo registerModelRequest =
registerAndLinkModelPreEvent.registerModelRequest();
+
+ Assertions.assertEquals("modelA", registerModelRequest.name());
+ Assertions.assertEquals(ImmutableMap.of("color", "#FFFFFF"),
registerModelRequest.properties());
+ Assertions.assertTrue(registerModelRequest.comment().isPresent());
+ String comment = registerModelRequest.comment().get();
+ Assertions.assertEquals("commentA", comment);
+ Assertions.assertFalse(registerModelRequest.audit().isPresent());
+ Assertions.assertFalse(registerModelRequest.lastVersion().isPresent());
+
+ // validate pre-event model version info
+ ModelVersionInfo modelVersionInfoPreEvent =
+ registerAndLinkModelPreEvent.linkModelVersionRequest();
+ Assertions.assertEquals("uriA", modelVersionInfoPreEvent.uri());
+ Assertions.assertTrue(modelVersionInfoPreEvent.aliases().isPresent());
+ String[] aliases = modelVersionInfoPreEvent.aliases().get();
+ Assertions.assertEquals(2, aliases.length);
+ Assertions.assertEquals("aliasProduction", aliases[0]);
+ Assertions.assertEquals("aliasTest", aliases[1]);
+ }
+
+ @Test
+ void testGetModelEvent() {
+ dispatcher.getModel(existingIdentA);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(GetModelPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.GET_MODEL, preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ GetModelPreEvent getModelPreEvent = (GetModelPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA, getModelPreEvent.identifier());
+ }
+
+ @Test
+ void testDeleteExistsModelEvent() {
+ dispatcher.deleteModel(existingIdentA);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(DeleteModelPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.DELETE_MODEL,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ DeleteModelPreEvent deleteModelPreEvent = (DeleteModelPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA, deleteModelPreEvent.identifier());
+ }
+
+ @Test
+ void testListModelEvent() {
+ dispatcher.listModels(namespace);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(ListModelPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.LIST_MODEL,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ ListModelPreEvent listModelPreEvent = (ListModelPreEvent) preEvent;
+ Assertions.assertEquals(namespace, listModelPreEvent.namespace());
+ }
+
+ @Test
+ void testLinkModelVersionEvent() {
+ dispatcher.linkModelVersion(
+ existingIdentA,
+ "uriA",
+ new String[] {"aliasProduction", "aliasTest"},
+ "versionInfoA",
+ ImmutableMap.of("color", "#FFFFFF"));
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(LinkModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.LINK_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ LinkModelVersionPreEvent linkModelVersionPreEvent =
(LinkModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA,
linkModelVersionPreEvent.identifier());
+ ModelVersionInfo modelVersionInfo =
linkModelVersionPreEvent.linkModelVersionRequest();
+
+ Assertions.assertEquals(1, modelVersionInfo.properties().size());
+ Assertions.assertEquals("#FFFFFF",
modelVersionInfo.properties().get("color"));
+
+ Assertions.assertEquals("uriA", modelVersionInfo.uri());
+ Assertions.assertTrue(modelVersionInfo.aliases().isPresent());
+ String[] aliases = modelVersionInfo.aliases().get();
+ Assertions.assertEquals(2, aliases.length);
+ Assertions.assertEquals("aliasProduction", aliases[0]);
+ Assertions.assertEquals("aliasTest", aliases[1]);
+
+ Assertions.assertTrue(modelVersionInfo.comment().isPresent());
+ String comment = modelVersionInfo.comment().get();
+ Assertions.assertEquals("versionInfoA", comment);
+
+ Assertions.assertFalse(modelVersionInfo.audit().isPresent());
+ }
+
+ @Test
+ void testGetModelVersionEventViaVersion() {
+ dispatcher.getModelVersion(existingIdentA, 1);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(GetModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.GET_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ GetModelVersionPreEvent getModelVersionPreEvent =
(GetModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA,
getModelVersionPreEvent.identifier());
+ }
+
+ @Test
+ void testGetModelVersionEventViaAlias() {
+ dispatcher.getModelVersion(existingIdentB, "aliasTest");
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(GetModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.GET_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ GetModelVersionPreEvent getModelVersionPreEvent =
(GetModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentB,
getModelVersionPreEvent.identifier());
+ Assertions.assertTrue(getModelVersionPreEvent.alias().isPresent());
+ Assertions.assertEquals("aliasTest",
getModelVersionPreEvent.alias().get());
+ Assertions.assertFalse(getModelVersionPreEvent.version().isPresent());
+ }
+
+ @Test
+ void testDeleteModelVersionEventViaVersion() {
+ dispatcher.deleteModelVersion(existingIdentA, 1);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(DeleteModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.DELETE_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ DeleteModelVersionPreEvent deleteModelVersionPreEvent =
(DeleteModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA,
deleteModelVersionPreEvent.identifier());
+ Assertions.assertTrue(deleteModelVersionPreEvent.version().isPresent());
+ Assertions.assertEquals(1, deleteModelVersionPreEvent.version().get());
+ Assertions.assertFalse(deleteModelVersionPreEvent.alias().isPresent());
+ }
+
+ @Test
+ void testDeleteModelVersionEventViaAlias() {
+ dispatcher.deleteModelVersion(existingIdentB, "aliasTest");
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(DeleteModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.DELETE_MODEL_VERSION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ DeleteModelVersionPreEvent deleteModelVersionPreEvent =
(DeleteModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentB,
deleteModelVersionPreEvent.identifier());
+ Assertions.assertTrue(deleteModelVersionPreEvent.alias().isPresent());
+ Assertions.assertEquals("aliasTest",
deleteModelVersionPreEvent.alias().get());
+ Assertions.assertFalse(deleteModelVersionPreEvent.version().isPresent());
+ }
+
+ @Test
+ void testListModelVersionsEvent() {
+ dispatcher.listModelVersions(existingIdentA);
+
+ // validate pre-event
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(ListModelVersionPreEvent.class,
preEvent.getClass());
+ Assertions.assertEquals(OperationType.LIST_MODEL_VERSIONS,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+
+ ListModelVersionPreEvent listModelVersionsPreEvent =
(ListModelVersionPreEvent) preEvent;
+ Assertions.assertEquals(existingIdentA,
listModelVersionsPreEvent.identifier());
+ }
+
+ private ModelDispatcher mockExceptionModelDispatcher() {
+ return mock(
+ ModelDispatcher.class,
+ invocation -> {
+ throw new GravitinoRuntimeException("Exception for all methods");
+ });
+ }
+
+ private ModelDispatcher mockTagDispatcher() {
+ ModelDispatcher dispatcher = mock(ModelDispatcher.class);
+
+ when(dispatcher.registerModel(existingIdentA, "commentA",
ImmutableMap.of("color", "#FFFFFF")))
+ .thenReturn(modelA);
+ when(dispatcher.registerModel(existingIdentB, "commentB",
ImmutableMap.of("color", "#FFFFFF")))
+ .thenReturn(modelB);
+
+ when(dispatcher.getModel(existingIdentA)).thenReturn(modelA);
+ when(dispatcher.getModel(existingIdentB)).thenReturn(modelB);
+
+ when(dispatcher.deleteModel(existingIdentA)).thenReturn(true);
+ when(dispatcher.deleteModel(notExistingIdent)).thenReturn(false);
+
+ when(dispatcher.listModels(namespace))
+ .thenReturn(new NameIdentifier[] {existingIdentA, existingIdentB});
+
+ when(dispatcher.getModelVersion(existingIdentA,
1)).thenReturn(firstModelVersion);
+ when(dispatcher.getModelVersion(existingIdentB,
"aliasTest")).thenReturn(secondModelVersion);
+
+ when(dispatcher.deleteModelVersion(existingIdentA, 1)).thenReturn(true);
+ when(dispatcher.deleteModelVersion(existingIdentB,
"aliasTest")).thenReturn(true);
+ when(dispatcher.deleteModelVersion(existingIdentA, 3)).thenReturn(false);
+
+ when(dispatcher.listModelVersions(existingIdentA)).thenReturn(new int[]
{1, 2});
+
+ return dispatcher;
+ }
+
+ private Model getMockModel(String name, String comment) {
+ return getMockModel(name, comment, ImmutableMap.of("color", "#FFFFFF"));
+ }
+
+ private Model getMockModel(String name, String comment, Map<String, String>
properties) {
+ Model mockModel = mock(Model.class);
+ when(mockModel.name()).thenReturn(name);
+ when(mockModel.comment()).thenReturn(comment);
+ when(mockModel.properties()).thenReturn(properties);
+ when(mockModel.latestVersion()).thenReturn(1);
+ when(mockModel.auditInfo()).thenReturn(null);
+
+ return mockModel;
+ }
+
+ private Model getMockModelWithAudit(String name, String comment) {
+ Model model = getMockModel(name, comment);
+ Audit mockAudit = mock(Audit.class);
+
+ when(mockAudit.creator()).thenReturn("demo_user");
+
when(mockAudit.createTime()).thenReturn(Instant.ofEpochMilli(1611111111111L));
+ when(mockAudit.lastModifier()).thenReturn("demo_user");
+
when(mockAudit.lastModifiedTime()).thenReturn(Instant.ofEpochMilli(1611111111111L));
+ when(model.auditInfo()).thenReturn(mockAudit);
+
+ return model;
+ }
+
+ private ModelVersion mockModelVersion(String uri, String[] aliases, String
comment) {
+ ModelVersion modelVersion = mock(ModelVersion.class);
+ when(modelVersion.version()).thenReturn(1);
+ when(modelVersion.uri()).thenReturn(uri);
+ when(modelVersion.aliases()).thenReturn(aliases);
+ when(modelVersion.comment()).thenReturn("model version " + comment);
+ when(modelVersion.properties()).thenReturn(ImmutableMap.of("color",
"#FFFFFF"));
+
+ return modelVersion;
+ }
+}
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index 88edf23470..3f30c2f2c2 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -129,15 +129,16 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
##### Pre-event
-| Operation type | Pre-event
| Since Version |
-|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------|
-| Iceberg REST server table operation | `IcebergCreateTablePreEvent`,
`IcebergUpdateTablePreEvent`, `IcebergDropTablePreEvent`,
`IcebergLoadTablePreEvent`, `IcebergListTablePreEvent`,
`IcebergTableExistsPreEvent`, `IcebergRenameTablePreEvent` | 0.7.0-incubating |
-| Gravitino server table operation | `CreateTablePreEvent`,
`AlterTablePreEvent`, `DropTablePreEvent`, `PurgeTablePreEvent`,
`LoadTablePreEvent`, `ListTablePreEvent`
| 0.8.0-incubating |
-| Gravitino server schema operation | `CreateSchemaPreEvent`,
`AlterSchemaPreEvent`, `DropSchemaPreEvent`, `LoadSchemaPreEvent`,
`ListSchemaPreEvent`
| 0.8.0-incubating |
-| Gravitino server catalog operation | `CreateCatalogPreEvent`,
`AlterCatalogPreEvent`, `DropCatalogPreEvent`, `LoadCatalogPreEvent`,
`ListCatalogPreEvent`
| 0.8.0-incubating |
-| Gravitino server metalake operation | `CreateMetalakePreEvent`,
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
| 0.8.0-incubating |
-| Gravitino server partition operation | `AddPartitionPreEvent`,
`DropPartitionPreEvent`, `GetPartitionPreEvent`,
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`
| 0.8.0-incubating |
-| Gravitino server fileset operation | `CreateFilesetPreEvent`,
`AlterFilesetPreEvent`, `DropFilesetPreEvent`,
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`
| 0.8.0-incubating |
+| Operation type | Pre-event
| Since Version |
+|--------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------|
+| Iceberg REST server table operation | `IcebergCreateTablePreEvent`,
`IcebergUpdateTablePreEvent`, `IcebergDropTablePreEvent`,
`IcebergLoadTablePreEvent`, `IcebergListTablePreEvent`,
`IcebergTableExistsPreEvent`, `IcebergRenameTablePreEvent`
| 0.7.0-incubating |
+| Gravitino server table operation | `CreateTablePreEvent`,
`AlterTablePreEvent`, `DropTablePreEvent`, `PurgeTablePreEvent`,
`LoadTablePreEvent`, `ListTablePreEvent`
|
0.8.0-incubating |
+| Gravitino server schema operation | `CreateSchemaPreEvent`,
`AlterSchemaPreEvent`, `DropSchemaPreEvent`, `LoadSchemaPreEvent`,
`ListSchemaPreEvent`
|
0.8.0-incubating |
+| Gravitino server catalog operation | `CreateCatalogPreEvent`,
`AlterCatalogPreEvent`, `DropCatalogPreEvent`, `LoadCatalogPreEvent`,
`ListCatalogPreEvent`
| 0.8.0-incubating |
+| Gravitino server metalake operation | `CreateMetalakePreEvent`,
`AlterMetalakePreEvent`,`DropMetalakePreEvent`,`LoadMetalakePreEvent`,`ListMetalakePreEvent`
| 0.8.0-incubating |
+| Gravitino server partition operation | `AddPartitionPreEvent`,
`DropPartitionPreEvent`, `GetPartitionPreEvent`,
`PurgePartitionPreEvent`,`ListPartitionPreEvent`,`ListPartitionNamesPreEvent`
| 0.8.0-incubating |
+| Gravitino server fileset operation | `CreateFilesetPreEvent`,
`AlterFilesetPreEvent`, `DropFilesetPreEvent`,
`LoadFilesetPreEvent`,`ListFilesetPreEvent`,`GetFileLocationPreEvent`
| 0.8.0-incubating |
+| Gravitino server model operation | `DeleteModelPreEvent`,
`DeleteModelVersionPreEvent`,
`RegisterAndLinkModelPreEvent`,`GetModelPreEvent`,
`GetModelVersionPreEvent`,`LinkModelVersionPreEvent`,`ListModelPreEvent`,`RegisterModelPreEvent`
|
0.9.0-incubating |
| Gravitino server tag operation | `ListTagsPreEvent`,
`ListTagsInfoPreEvent`, `CreateTagPreEvent`, `GetTagPreEvent`,
`AlterTagPreEvent`, `DeleteTagPreEvent`, `ListMetadataObjectsForTagPreEvent`,
`ListTagsForMetadataObjectPreEvent`, `ListTagsInfoForMetadataObjectPreEvent`,
`AssociateTagsForMetadataObjectPreEvent`, `GetTagForMetadataObjectPreEvent` |
0.9.0-incubating |
#### Event listener plugin