This is an automated email from the ASF dual-hosted git repository.
mchades 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 6c0e75aa1e [#9536] feat(core): Add event listener for function
operations (#10499)
6c0e75aa1e is described below
commit 6c0e75aa1e5f999d6a52290fb678536fb4fe24f3
Author: akshay thorat <[email protected]>
AuthorDate: Thu Mar 26 18:37:31 2026 -0700
[#9536] feat(core): Add event listener for function operations (#10499)
### What changes were proposed in this pull request?
Add event/listener hooks for function CRUD operations (register, get,
alter, drop, list). This follows the same pattern as existing entity
event dispatchers (Table, Model, etc.).
### Why are the changes needed?
New files:
- FunctionInfo: read-only function info for event listeners
- FunctionEvent/FunctionFailureEvent/FunctionPreEvent: base event
classes
- Register/Get/Alter/Drop/ListFunction Event/PreEvent/FailureEvent
classes
- FunctionEventDispatcher: decorates FunctionDispatcher with event
dispatching
- TestFunctionEvent: unit tests for all function events
Modified files:
- OperationType: added REGISTER/GET/ALTER/DROP/LIST_FUNCTION
- GravitinoEnv: wired FunctionEventDispatcher into dispatcher chain
Closes #9536
### Does this PR introduce _any_ user-facing change?
No
### How was this patch tested?
All tests passed
---
.../java/org/apache/gravitino/GravitinoEnv.java | 11 +-
.../listener/FunctionEventDispatcher.java | 176 ++++++++++
.../listener/api/event/OperationType.java | 8 +
.../api/event/function/AlterFunctionEvent.java | 77 +++++
.../event/function/AlterFunctionFailureEvent.java | 67 ++++
.../api/event/function/AlterFunctionPreEvent.java | 53 +++
.../api/event/function/DropFunctionEvent.java | 58 ++++
.../event/function/DropFunctionFailureEvent.java | 47 +++
.../api/event/function/DropFunctionPreEvent.java | 37 +++
.../listener/api/event/function/FunctionEvent.java | 48 +++
.../api/event/function/FunctionFailureEvent.java | 42 +++
.../api/event/function/FunctionPreEvent.java | 32 ++
.../api/event/function/GetFunctionEvent.java | 58 ++++
.../event/function/GetFunctionFailureEvent.java | 44 +++
.../api/event/function/GetFunctionPreEvent.java | 37 +++
.../api/event/function/ListFunctionEvent.java | 59 ++++
.../event/function/ListFunctionFailureEvent.java | 60 ++++
.../api/event/function/ListFunctionInfosEvent.java | 72 +++++
.../api/event/function/ListFunctionPreEvent.java | 50 +++
.../api/event/function/RegisterFunctionEvent.java | 59 ++++
.../function/RegisterFunctionFailureEvent.java | 67 ++++
.../event/function/RegisterFunctionPreEvent.java | 52 +++
.../gravitino/listener/api/info/FunctionInfo.java | 141 ++++++++
.../listener/api/event/TestFunctionEvent.java | 360 +++++++++++++++++++++
docs/gravitino-server-config.md | 2 +
25 files changed, 1712 insertions(+), 5 deletions(-)
diff --git a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
index 4918457bd0..d7c84baca3 100644
--- a/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
+++ b/core/src/main/java/org/apache/gravitino/GravitinoEnv.java
@@ -75,6 +75,7 @@ import org.apache.gravitino.listener.CatalogEventDispatcher;
import org.apache.gravitino.listener.EventBus;
import org.apache.gravitino.listener.EventListenerManager;
import org.apache.gravitino.listener.FilesetEventDispatcher;
+import org.apache.gravitino.listener.FunctionEventDispatcher;
import org.apache.gravitino.listener.JobEventDispatcher;
import org.apache.gravitino.listener.MetalakeEventDispatcher;
import org.apache.gravitino.listener.ModelEventDispatcher;
@@ -612,15 +613,15 @@ public class GravitinoEnv {
new ModelNormalizeDispatcher(modelHookDispatcher, catalogManager);
this.modelDispatcher = new ModelEventDispatcher(eventBus,
modelNormalizeDispatcher);
- // TODO: Add FunctionHookDispatcher and FunctionEventDispatcher when needed
- // The operation chain should be:
- // FunctionEventDispatcher -> FunctionNormalizeDispatcher ->
FunctionHookDispatcher ->
- // FunctionOperationDispatcher
+ // TODO: Add FunctionHookDispatcher when needed
+ // The operation chain is:
+ // FunctionEventDispatcher -> FunctionNormalizeDispatcher ->
FunctionOperationDispatcher
FunctionOperationDispatcher functionOperationDispatcher =
new FunctionOperationDispatcher(
catalogManager, schemaOperationDispatcher, entityStore,
idGenerator);
- this.functionDispatcher =
+ FunctionNormalizeDispatcher functionNormalizeDispatcher =
new FunctionNormalizeDispatcher(functionOperationDispatcher,
catalogManager);
+ this.functionDispatcher = new FunctionEventDispatcher(eventBus,
functionNormalizeDispatcher);
// TODO: Add ViewHookDispatcher and ViewEventDispatcher when needed for
view-specific hooks
// and event handling.
diff --git
a/core/src/main/java/org/apache/gravitino/listener/FunctionEventDispatcher.java
b/core/src/main/java/org/apache/gravitino/listener/FunctionEventDispatcher.java
new file mode 100644
index 0000000000..52eba85e04
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/FunctionEventDispatcher.java
@@ -0,0 +1,176 @@
+/*
+ * 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.Arrays;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.catalog.FunctionDispatcher;
+import org.apache.gravitino.exceptions.FunctionAlreadyExistsException;
+import org.apache.gravitino.exceptions.NoSuchFunctionException;
+import org.apache.gravitino.exceptions.NoSuchSchemaException;
+import org.apache.gravitino.function.Function;
+import org.apache.gravitino.function.FunctionChange;
+import org.apache.gravitino.function.FunctionDefinition;
+import org.apache.gravitino.function.FunctionType;
+import org.apache.gravitino.listener.api.event.function.AlterFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.AlterFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.AlterFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.DropFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.DropFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.DropFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.GetFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.GetFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.GetFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.ListFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionInfosEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.RegisterFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.RegisterFunctionFailureEvent;
+import
org.apache.gravitino.listener.api.event.function.RegisterFunctionPreEvent;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+import org.apache.gravitino.utils.PrincipalUtils;
+
+/**
+ * {@code FunctionEventDispatcher} is a decorator for {@link
FunctionDispatcher} that not only
+ * delegates function operations to the underlying dispatcher but also
dispatches corresponding
+ * events to an {@link EventBus} after each operation is completed.
+ */
+public class FunctionEventDispatcher implements FunctionDispatcher {
+
+ private final EventBus eventBus;
+ private final FunctionDispatcher dispatcher;
+
+ /**
+ * Constructs a FunctionEventDispatcher with a specified EventBus and
FunctionDispatcher.
+ *
+ * @param eventBus The EventBus to which events will be dispatched.
+ * @param dispatcher The underlying {@link FunctionDispatcher} that will
perform the actual
+ * function operations.
+ */
+ public FunctionEventDispatcher(EventBus eventBus, FunctionDispatcher
dispatcher) {
+ this.eventBus = eventBus;
+ this.dispatcher = dispatcher;
+ }
+
+ @Override
+ public NameIdentifier[] listFunctions(Namespace namespace) throws
NoSuchSchemaException {
+ String user = PrincipalUtils.getCurrentUserName();
+ eventBus.dispatchEvent(new ListFunctionPreEvent(user, namespace));
+ try {
+ NameIdentifier[] nameIdentifiers = dispatcher.listFunctions(namespace);
+ eventBus.dispatchEvent(new ListFunctionEvent(user, namespace));
+ return nameIdentifiers;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(new ListFunctionFailureEvent(user, namespace, e));
+ throw e;
+ }
+ }
+
+ @Override
+ public Function[] listFunctionInfos(Namespace namespace) throws
NoSuchSchemaException {
+ String user = PrincipalUtils.getCurrentUserName();
+ eventBus.dispatchEvent(new ListFunctionPreEvent(user, namespace));
+ try {
+ Function[] functions = dispatcher.listFunctionInfos(namespace);
+ FunctionInfo[] functionInfos =
+
Arrays.stream(functions).map(FunctionInfo::new).toArray(FunctionInfo[]::new);
+ eventBus.dispatchEvent(new ListFunctionInfosEvent(user, namespace,
functionInfos));
+ return functions;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(new ListFunctionFailureEvent(user, namespace, e));
+ throw e;
+ }
+ }
+
+ @Override
+ public Function getFunction(NameIdentifier ident) throws
NoSuchFunctionException {
+ String user = PrincipalUtils.getCurrentUserName();
+ eventBus.dispatchEvent(new GetFunctionPreEvent(user, ident));
+ try {
+ Function function = dispatcher.getFunction(ident);
+ eventBus.dispatchEvent(new GetFunctionEvent(user, ident, new
FunctionInfo(function)));
+ return function;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(new GetFunctionFailureEvent(user, ident, e));
+ throw e;
+ }
+ }
+
+ @Override
+ public Function registerFunction(
+ NameIdentifier ident,
+ String comment,
+ FunctionType functionType,
+ boolean deterministic,
+ FunctionDefinition[] definitions)
+ throws NoSuchSchemaException, FunctionAlreadyExistsException {
+ String user = PrincipalUtils.getCurrentUserName();
+ FunctionInfo registerFunctionRequest =
+ new FunctionInfo(ident.name(), functionType, deterministic, comment,
definitions, null);
+ eventBus.dispatchEvent(new RegisterFunctionPreEvent(user, ident,
registerFunctionRequest));
+ try {
+ Function function =
+ dispatcher.registerFunction(ident, comment, functionType,
deterministic, definitions);
+ eventBus.dispatchEvent(new RegisterFunctionEvent(user, ident, new
FunctionInfo(function)));
+ return function;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(
+ new RegisterFunctionFailureEvent(user, ident, e,
registerFunctionRequest));
+ throw e;
+ }
+ }
+
+ @Override
+ public Function alterFunction(NameIdentifier ident, FunctionChange...
changes)
+ throws NoSuchFunctionException, IllegalArgumentException {
+ String user = PrincipalUtils.getCurrentUserName();
+ eventBus.dispatchEvent(new AlterFunctionPreEvent(user, ident, changes));
+ try {
+ Function function = dispatcher.alterFunction(ident, changes);
+ eventBus.dispatchEvent(
+ new AlterFunctionEvent(user, ident, changes, new
FunctionInfo(function)));
+ return function;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(new AlterFunctionFailureEvent(user, ident, e,
changes));
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean dropFunction(NameIdentifier ident) {
+ String user = PrincipalUtils.getCurrentUserName();
+ eventBus.dispatchEvent(new DropFunctionPreEvent(user, ident));
+ try {
+ boolean isExists = dispatcher.dropFunction(ident);
+ eventBus.dispatchEvent(new DropFunctionEvent(user, ident, isExists));
+ return isExists;
+ } catch (Exception e) {
+ eventBus.dispatchEvent(new DropFunctionFailureEvent(user, ident, e));
+ throw e;
+ }
+ }
+
+ @Override
+ public boolean functionExists(NameIdentifier ident) {
+ return dispatcher.functionExists(ident);
+ }
+}
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 948c50caa2..97c0c9fcee 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
@@ -188,5 +188,13 @@ public enum OperationType {
ASSOCIATE_POLICIES_FOR_METADATA_OBJECT,
GET_POLICY_FOR_METADATA_OBJECT,
+ // Function operations
+ REGISTER_FUNCTION,
+ GET_FUNCTION,
+ ALTER_FUNCTION,
+ DROP_FUNCTION,
+ LIST_FUNCTION,
+ LIST_FUNCTION_INFOS,
+
UNKNOWN,
}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionEvent.java
new file mode 100644
index 0000000000..e4e0418118
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionEvent.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.function;
+
+import java.util.Arrays;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.function.FunctionChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/** Represents an event fired when a function is successfully altered. */
+@DeveloperApi
+public final class AlterFunctionEvent extends FunctionEvent {
+ private final FunctionInfo updatedFunctionInfo;
+ private final FunctionChange[] functionChanges;
+
+ /**
+ * Constructs an instance of {@code AlterFunctionEvent}.
+ *
+ * @param user The username of the individual responsible for initiating the
function alteration.
+ * @param identifier The unique identifier of the altered function.
+ * @param functionChanges An array of {@link FunctionChange} objects
representing the specific
+ * changes applied to the function.
+ * @param updatedFunctionInfo The post-alteration state of the function.
+ */
+ public AlterFunctionEvent(
+ String user,
+ NameIdentifier identifier,
+ FunctionChange[] functionChanges,
+ FunctionInfo updatedFunctionInfo) {
+ super(user, identifier);
+ this.functionChanges = Arrays.copyOf(functionChanges,
functionChanges.length);
+ this.updatedFunctionInfo = updatedFunctionInfo;
+ }
+
+ /**
+ * Retrieves the updated state of the function after the successful
alteration.
+ *
+ * @return A {@link FunctionInfo} instance encapsulating the details of the
altered function.
+ */
+ public FunctionInfo updatedFunctionInfo() {
+ return updatedFunctionInfo;
+ }
+
+ /**
+ * Retrieves the specific changes that were made to the function during the
alteration process.
+ *
+ * @return An array of {@link FunctionChange} objects detailing each
modification applied to the
+ * function.
+ */
+ public FunctionChange[] functionChanges() {
+ return Arrays.copyOf(functionChanges, functionChanges.length);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionFailureEvent.java
new file mode 100644
index 0000000000..bc3c760d86
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionFailureEvent.java
@@ -0,0 +1,67 @@
+/*
+ * 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.function;
+
+import java.util.Arrays;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.function.FunctionChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/**
+ * Represents an event that is triggered when an attempt to alter a function
fails due to an
+ * exception.
+ */
+@DeveloperApi
+public final class AlterFunctionFailureEvent extends FunctionFailureEvent {
+ private final FunctionChange[] functionChanges;
+
+ /**
+ * Constructs an {@code AlterFunctionFailureEvent} instance.
+ *
+ * @param user The user who initiated the function alteration operation.
+ * @param identifier The identifier of the function that was attempted to be
altered.
+ * @param exception The exception that was thrown during the function
alteration operation.
+ * @param functionChanges The changes that were attempted on the function.
+ */
+ public AlterFunctionFailureEvent(
+ String user,
+ NameIdentifier identifier,
+ Exception exception,
+ FunctionChange[] functionChanges) {
+ super(user, identifier, exception);
+ this.functionChanges = Arrays.copyOf(functionChanges,
functionChanges.length);
+ }
+
+ /**
+ * Retrieves the changes that were attempted on the function.
+ *
+ * @return An array of {@link FunctionChange} objects representing the
attempted modifications to
+ * the function.
+ */
+ public FunctionChange[] functionChanges() {
+ return Arrays.copyOf(functionChanges, functionChanges.length);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionPreEvent.java
new file mode 100644
index 0000000000..d599f222d0
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/AlterFunctionPreEvent.java
@@ -0,0 +1,53 @@
+/*
+ * 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.function;
+
+import java.util.Arrays;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.function.FunctionChange;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event triggered before altering a function. */
+@DeveloperApi
+public class AlterFunctionPreEvent extends FunctionPreEvent {
+ private final FunctionChange[] functionChanges;
+
+ public AlterFunctionPreEvent(
+ String user, NameIdentifier identifier, FunctionChange[]
functionChanges) {
+ super(user, identifier);
+ this.functionChanges = Arrays.copyOf(functionChanges,
functionChanges.length);
+ }
+
+ /**
+ * Retrieves the specific changes that were made to the function during the
alteration process.
+ *
+ * @return An array of {@link FunctionChange} objects detailing each
modification applied to the
+ * function.
+ */
+ public FunctionChange[] functionChanges() {
+ return Arrays.copyOf(functionChanges, functionChanges.length);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.ALTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionEvent.java
new file mode 100644
index 0000000000..7ab1f63ab1
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionEvent.java
@@ -0,0 +1,58 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event that is generated after a function is successfully
dropped. */
+@DeveloperApi
+public final class DropFunctionEvent extends FunctionEvent {
+ private final boolean isExists;
+
+ /**
+ * Constructs a new {@code DropFunctionEvent} instance.
+ *
+ * @param user The user who initiated the drop function operation.
+ * @param identifier The identifier of the function that was attempted to be
dropped.
+ * @param isExists A boolean flag indicating whether the function existed at
the time of the drop
+ * operation.
+ */
+ public DropFunctionEvent(String user, NameIdentifier identifier, boolean
isExists) {
+ super(user, identifier);
+ this.isExists = isExists;
+ }
+
+ /**
+ * Retrieves the existence status of the function at the time of the drop
operation.
+ *
+ * @return A boolean value indicating whether the function existed. {@code
true} if the function
+ * existed, otherwise {@code false}.
+ */
+ public boolean isExists() {
+ return isExists;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.DROP_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionFailureEvent.java
new file mode 100644
index 0000000000..2fa4694107
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionFailureEvent.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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/**
+ * Represents an event that is generated when an attempt to drop a function
fails due to an
+ * exception.
+ */
+@DeveloperApi
+public final class DropFunctionFailureEvent extends FunctionFailureEvent {
+ /**
+ * Constructs a new {@code DropFunctionFailureEvent} instance.
+ *
+ * @param user The user who initiated the drop function operation.
+ * @param identifier The identifier of the function that the operation
attempted to drop.
+ * @param exception The exception that was thrown during the drop function
operation.
+ */
+ public DropFunctionFailureEvent(String user, NameIdentifier identifier,
Exception exception) {
+ super(user, identifier, exception);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.DROP_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionPreEvent.java
new file mode 100644
index 0000000000..863635a157
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/DropFunctionPreEvent.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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event that is triggered before dropping a function. */
+@DeveloperApi
+public class DropFunctionPreEvent extends FunctionPreEvent {
+ public DropFunctionPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.DROP_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionEvent.java
new file mode 100644
index 0000000000..5bde5e981b
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionEvent.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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.Event;
+import org.apache.gravitino.listener.api.event.OperationStatus;
+
+/**
+ * Represents an abstract base class for events related to function
operations. This class extends
+ * {@link Event} to provide a more specific context involving operations on
functions, such as
+ * registration, deletion, or modification.
+ */
+@DeveloperApi
+public abstract class FunctionEvent extends Event {
+ /**
+ * Constructs a new {@code FunctionEvent} with the specified user and
function identifier.
+ *
+ * @param user The user responsible for triggering the function operation.
+ * @param identifier The identifier of the function involved in the
operation.
+ */
+ protected FunctionEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ @Override
+ public OperationStatus operationStatus() {
+ return OperationStatus.SUCCESS;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionFailureEvent.java
new file mode 100644
index 0000000000..dfeae48922
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionFailureEvent.java
@@ -0,0 +1,42 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.FailureEvent;
+
+/**
+ * An abstract class representing events that are triggered when a function
operation fails due to
+ * an exception.
+ */
+@DeveloperApi
+public abstract class FunctionFailureEvent extends FailureEvent {
+ /**
+ * Constructs a new {@code FunctionFailureEvent} instance.
+ *
+ * @param user The user associated with the failed function operation.
+ * @param identifier The identifier of the function involved in the failed
operation.
+ * @param exception The exception that was thrown during the function
operation.
+ */
+ protected FunctionFailureEvent(String user, NameIdentifier identifier,
Exception exception) {
+ super(user, identifier, exception);
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionPreEvent.java
new file mode 100644
index 0000000000..76bef1b52d
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/FunctionPreEvent.java
@@ -0,0 +1,32 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.PreEvent;
+
+/** Represents a pre-event for function operations. */
+@DeveloperApi
+public abstract class FunctionPreEvent extends PreEvent {
+ protected FunctionPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionEvent.java
new file mode 100644
index 0000000000..1ae131c839
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionEvent.java
@@ -0,0 +1,58 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/** Represents an event triggered upon the successful retrieval of a function.
*/
+@DeveloperApi
+public final class GetFunctionEvent extends FunctionEvent {
+ private final FunctionInfo functionInfo;
+
+ /**
+ * Constructs an instance of {@code GetFunctionEvent}.
+ *
+ * @param user The username of the individual who initiated the function
retrieval.
+ * @param identifier The unique identifier of the function that was
retrieved.
+ * @param functionInfo The state of the function post-retrieval.
+ */
+ public GetFunctionEvent(String user, NameIdentifier identifier, FunctionInfo
functionInfo) {
+ super(user, identifier);
+ this.functionInfo = functionInfo;
+ }
+
+ /**
+ * Retrieves the state of the function as it was made available to the user
after successful
+ * retrieval.
+ *
+ * @return A {@link FunctionInfo} instance encapsulating the details of the
function as retrieved.
+ */
+ public FunctionInfo functionInfo() {
+ return functionInfo;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.GET_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionFailureEvent.java
new file mode 100644
index 0000000000..d5261a8550
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionFailureEvent.java
@@ -0,0 +1,44 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event that occurs when an attempt to get a function fails
due to an exception. */
+@DeveloperApi
+public final class GetFunctionFailureEvent extends FunctionFailureEvent {
+ /**
+ * Constructs a {@code GetFunctionFailureEvent} instance.
+ *
+ * @param user The user who initiated the function retrieval operation.
+ * @param identifier The identifier of the function that the retrieval
attempt was made for.
+ * @param exception The exception that was thrown during the function
retrieval operation.
+ */
+ public GetFunctionFailureEvent(String user, NameIdentifier identifier,
Exception exception) {
+ super(user, identifier, exception);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.GET_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionPreEvent.java
new file mode 100644
index 0000000000..ed33f91fb2
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/GetFunctionPreEvent.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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event triggered before getting a function. */
+@DeveloperApi
+public class GetFunctionPreEvent extends FunctionPreEvent {
+ public GetFunctionPreEvent(String user, NameIdentifier identifier) {
+ super(user, identifier);
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.GET_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionEvent.java
new file mode 100644
index 0000000000..5d2853bcef
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionEvent.java
@@ -0,0 +1,59 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/**
+ * Represents an event that is triggered upon the successful listing of
functions within a
+ * namespace.
+ */
+@DeveloperApi
+public final class ListFunctionEvent extends FunctionEvent {
+ private final Namespace namespace;
+
+ /**
+ * Constructs an instance of {@code ListFunctionEvent}.
+ *
+ * @param user The username of the individual who initiated the function
listing.
+ * @param namespace The namespace from which functions were listed.
+ */
+ public ListFunctionEvent(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 functions were listed.
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionFailureEvent.java
new file mode 100644
index 0000000000..6a645c5fca
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionFailureEvent.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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/**
+ * Represents an event that is triggered when an attempt to list functions
within a namespace fails
+ * due to an exception.
+ */
+@DeveloperApi
+public final class ListFunctionFailureEvent extends FunctionFailureEvent {
+ private final Namespace namespace;
+
+ /**
+ * Constructs a {@code ListFunctionFailureEvent} instance.
+ *
+ * @param user The username of the individual who initiated the operation to
list functions.
+ * @param namespace The namespace for which the function listing was
attempted.
+ * @param exception The exception encountered during the attempt to list
functions.
+ */
+ public ListFunctionFailureEvent(String user, Namespace namespace, Exception
exception) {
+ super(user, NameIdentifier.of(namespace.levels()), exception);
+ this.namespace = namespace;
+ }
+
+ /**
+ * Retrieves the namespace associated with this failure event.
+ *
+ * @return A {@link Namespace} instance for which the function listing was
attempted.
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionInfosEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionInfosEvent.java
new file mode 100644
index 0000000000..be5d30a21f
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionInfosEvent.java
@@ -0,0 +1,72 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/**
+ * Represents an event that is triggered upon the successful listing of
function infos within a
+ * namespace.
+ */
+@DeveloperApi
+public final class ListFunctionInfosEvent extends FunctionEvent {
+ private final Namespace namespace;
+ private final FunctionInfo[] functionInfos;
+
+ /**
+ * Constructs an instance of {@code ListFunctionInfosEvent}.
+ *
+ * @param user The username of the individual who initiated the function
info listing.
+ * @param namespace The namespace from which function infos were listed.
+ * @param functionInfos The function infos that were listed.
+ */
+ public ListFunctionInfosEvent(String user, Namespace namespace,
FunctionInfo[] functionInfos) {
+ super(user, NameIdentifier.of(namespace.levels()));
+ this.namespace = namespace;
+ this.functionInfos = functionInfos;
+ }
+
+ /**
+ * Provides the namespace associated with this event.
+ *
+ * @return A {@link Namespace} instance from which function infos were
listed.
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ /**
+ * Provides the function infos associated with this event.
+ *
+ * @return An array of {@link FunctionInfo} instances that were listed.
+ */
+ public FunctionInfo[] functionInfos() {
+ return functionInfos;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_FUNCTION_INFOS;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionPreEvent.java
new file mode 100644
index 0000000000..89d221ed67
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/ListFunctionPreEvent.java
@@ -0,0 +1,50 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+
+/** Represents an event that is triggered before listing functions within a
namespace. */
+@DeveloperApi
+public class ListFunctionPreEvent extends FunctionPreEvent {
+ private final Namespace namespace;
+
+ public ListFunctionPreEvent(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 functions were listed.
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.LIST_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionEvent.java
new file mode 100644
index 0000000000..291eac493f
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionEvent.java
@@ -0,0 +1,59 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/** Represents an event triggered upon the successful registration of a
function. */
+@DeveloperApi
+public final class RegisterFunctionEvent extends FunctionEvent {
+ private final FunctionInfo registeredFunctionInfo;
+
+ /**
+ * Constructs an instance of {@code RegisterFunctionEvent}.
+ *
+ * @param user The username of the individual who initiated the function
registration.
+ * @param identifier The unique identifier of the function that was
registered.
+ * @param registeredFunctionInfo The final state of the function
post-registration.
+ */
+ public RegisterFunctionEvent(
+ String user, NameIdentifier identifier, FunctionInfo
registeredFunctionInfo) {
+ super(user, identifier);
+ this.registeredFunctionInfo = registeredFunctionInfo;
+ }
+
+ /**
+ * Retrieves the final state of the function after successful registration.
+ *
+ * @return A {@link FunctionInfo} instance encapsulating the details of the
newly registered
+ * function.
+ */
+ public FunctionInfo registeredFunctionInfo() {
+ return registeredFunctionInfo;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.REGISTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionFailureEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionFailureEvent.java
new file mode 100644
index 0000000000..0a29a734ae
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionFailureEvent.java
@@ -0,0 +1,67 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/**
+ * Represents an event that is generated when an attempt to register a
function fails due to an
+ * exception.
+ */
+@DeveloperApi
+public final class RegisterFunctionFailureEvent extends FunctionFailureEvent {
+ private final FunctionInfo registerFunctionRequest;
+
+ /**
+ * Constructs a {@code RegisterFunctionFailureEvent} instance.
+ *
+ * @param user The user who initiated the function registration operation.
+ * @param identifier The identifier of the function that was attempted to be
registered.
+ * @param exception The exception that was thrown during the function
registration operation.
+ * @param registerFunctionRequest The original request information used to
attempt to register the
+ * function.
+ */
+ public RegisterFunctionFailureEvent(
+ String user,
+ NameIdentifier identifier,
+ Exception exception,
+ FunctionInfo registerFunctionRequest) {
+ super(user, identifier, exception);
+ this.registerFunctionRequest = registerFunctionRequest;
+ }
+
+ /**
+ * Retrieves the original request information for the attempted function
registration.
+ *
+ * @return The {@link FunctionInfo} instance representing the request
information for the failed
+ * function registration attempt.
+ */
+ public FunctionInfo registerFunctionRequest() {
+ return registerFunctionRequest;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.REGISTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionPreEvent.java
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionPreEvent.java
new file mode 100644
index 0000000000..fd84cda7bb
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/event/function/RegisterFunctionPreEvent.java
@@ -0,0 +1,52 @@
+/*
+ * 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.function;
+
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.listener.api.event.OperationType;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+
+/** Represents an event triggered before registering a function. */
+@DeveloperApi
+public class RegisterFunctionPreEvent extends FunctionPreEvent {
+ private final FunctionInfo registerFunctionRequest;
+
+ public RegisterFunctionPreEvent(
+ String user, NameIdentifier identifier, FunctionInfo
registerFunctionRequest) {
+ super(user, identifier);
+ this.registerFunctionRequest = registerFunctionRequest;
+ }
+
+ /**
+ * Retrieves the register function request.
+ *
+ * @return A {@link FunctionInfo} instance encapsulating the details of the
register function
+ * request.
+ */
+ public FunctionInfo registerFunctionRequest() {
+ return registerFunctionRequest;
+ }
+
+ @Override
+ public OperationType operationType() {
+ return OperationType.REGISTER_FUNCTION;
+ }
+}
diff --git
a/core/src/main/java/org/apache/gravitino/listener/api/info/FunctionInfo.java
b/core/src/main/java/org/apache/gravitino/listener/api/info/FunctionInfo.java
new file mode 100644
index 0000000000..0c09a6e722
--- /dev/null
+++
b/core/src/main/java/org/apache/gravitino/listener/api/info/FunctionInfo.java
@@ -0,0 +1,141 @@
+/*
+ * 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 java.util.Arrays;
+import javax.annotation.Nullable;
+import org.apache.gravitino.Audit;
+import org.apache.gravitino.annotation.DeveloperApi;
+import org.apache.gravitino.function.Function;
+import org.apache.gravitino.function.FunctionDefinition;
+import org.apache.gravitino.function.FunctionType;
+
+/**
+ * FunctionInfo exposes function 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 final class FunctionInfo {
+ private final String name;
+ private final FunctionType functionType;
+ private final boolean deterministic;
+ @Nullable private final String comment;
+ private final FunctionDefinition[] definitions;
+ @Nullable private final Audit auditInfo;
+
+ /**
+ * Constructs a FunctionInfo object from a Function instance.
+ *
+ * @param function The source Function instance.
+ */
+ public FunctionInfo(Function function) {
+ this(
+ function.name(),
+ function.functionType(),
+ function.deterministic(),
+ function.comment(),
+ function.definitions(),
+ function.auditInfo());
+ }
+
+ /**
+ * Constructs a FunctionInfo object with specified details.
+ *
+ * @param name Name of the function.
+ * @param functionType The function type (SCALAR, AGGREGATE, or TABLE).
+ * @param deterministic Whether the function is deterministic.
+ * @param comment Optional comment about the function.
+ * @param definitions The function definitions.
+ * @param auditInfo Optional audit information.
+ */
+ public FunctionInfo(
+ String name,
+ FunctionType functionType,
+ boolean deterministic,
+ String comment,
+ FunctionDefinition[] definitions,
+ Audit auditInfo) {
+ this.name = name;
+ this.functionType = functionType;
+ this.deterministic = deterministic;
+ this.comment = comment;
+ this.definitions =
+ definitions == null
+ ? new FunctionDefinition[0]
+ : Arrays.copyOf(definitions, definitions.length);
+ this.auditInfo = auditInfo;
+ }
+
+ /**
+ * Returns the name of the function.
+ *
+ * @return Function name.
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns the function type.
+ *
+ * @return The function type.
+ */
+ public FunctionType functionType() {
+ return functionType;
+ }
+
+ /**
+ * Returns whether the function is deterministic.
+ *
+ * @return True if the function is deterministic.
+ */
+ public boolean deterministic() {
+ return deterministic;
+ }
+
+ /**
+ * Returns the comment of the function.
+ *
+ * @return Function comment, or {@code null} if not available.
+ */
+ @Nullable
+ public String comment() {
+ return comment;
+ }
+
+ /**
+ * Returns the definitions of the function.
+ *
+ * @return Array of function definitions.
+ */
+ public FunctionDefinition[] definitions() {
+ return Arrays.copyOf(definitions, definitions.length);
+ }
+
+ /**
+ * Returns the audit information for the function.
+ *
+ * @return Audit information, or {@code null} if not available.
+ */
+ @Nullable
+ public Audit auditInfo() {
+ return auditInfo;
+ }
+}
diff --git
a/core/src/test/java/org/apache/gravitino/listener/api/event/TestFunctionEvent.java
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestFunctionEvent.java
new file mode 100644
index 0000000000..b1a2455aa7
--- /dev/null
+++
b/core/src/test/java/org/apache/gravitino/listener/api/event/TestFunctionEvent.java
@@ -0,0 +1,360 @@
+/*
+ * 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.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import org.apache.gravitino.NameIdentifier;
+import org.apache.gravitino.Namespace;
+import org.apache.gravitino.catalog.FunctionDispatcher;
+import org.apache.gravitino.exceptions.GravitinoRuntimeException;
+import org.apache.gravitino.function.Function;
+import org.apache.gravitino.function.FunctionChange;
+import org.apache.gravitino.function.FunctionDefinition;
+import org.apache.gravitino.function.FunctionType;
+import org.apache.gravitino.listener.DummyEventListener;
+import org.apache.gravitino.listener.EventBus;
+import org.apache.gravitino.listener.FunctionEventDispatcher;
+import org.apache.gravitino.listener.api.event.function.AlterFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.AlterFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.AlterFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.DropFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.DropFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.DropFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.GetFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.GetFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.GetFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.ListFunctionFailureEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionInfosEvent;
+import org.apache.gravitino.listener.api.event.function.ListFunctionPreEvent;
+import org.apache.gravitino.listener.api.event.function.RegisterFunctionEvent;
+import
org.apache.gravitino.listener.api.event.function.RegisterFunctionFailureEvent;
+import
org.apache.gravitino.listener.api.event.function.RegisterFunctionPreEvent;
+import org.apache.gravitino.listener.api.info.FunctionInfo;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestInstance.Lifecycle;
+
+@TestInstance(Lifecycle.PER_CLASS)
+public class TestFunctionEvent {
+ private FunctionEventDispatcher dispatcher;
+ private FunctionEventDispatcher failureDispatcher;
+ private DummyEventListener dummyEventListener;
+ private Function function;
+
+ @BeforeAll
+ void init() {
+ this.function = mockFunction();
+ this.dummyEventListener = new DummyEventListener();
+ EventBus eventBus = new EventBus(Arrays.asList(dummyEventListener));
+ FunctionDispatcher functionDispatcher = mockFunctionDispatcher();
+ this.dispatcher = new FunctionEventDispatcher(eventBus,
functionDispatcher);
+ FunctionDispatcher functionExceptionDispatcher =
mockExceptionFunctionDispatcher();
+ this.failureDispatcher = new FunctionEventDispatcher(eventBus,
functionExceptionDispatcher);
+ }
+
+ @Test
+ void testRegisterFunctionEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ dispatcher.registerFunction(
+ identifier,
+ function.comment(),
+ function.functionType(),
+ function.deterministic(),
+ function.definitions());
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(RegisterFunctionEvent.class, event.getClass());
+ FunctionInfo functionInfo = ((RegisterFunctionEvent)
event).registeredFunctionInfo();
+ checkFunctionInfo(functionInfo, function);
+ Assertions.assertEquals(OperationType.REGISTER_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(identifier, preEvent.identifier());
+ Assertions.assertEquals(RegisterFunctionPreEvent.class,
preEvent.getClass());
+ FunctionInfo requestInfo = ((RegisterFunctionPreEvent)
preEvent).registerFunctionRequest();
+ Assertions.assertEquals(function.functionType(),
requestInfo.functionType());
+ Assertions.assertEquals(function.deterministic(),
requestInfo.deterministic());
+ Assertions.assertEquals(OperationType.REGISTER_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testGetFunctionEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ dispatcher.getFunction(identifier);
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(GetFunctionEvent.class, event.getClass());
+ FunctionInfo functionInfo = ((GetFunctionEvent) event).functionInfo();
+ checkFunctionInfo(functionInfo, function);
+ Assertions.assertEquals(OperationType.GET_FUNCTION, event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(identifier, preEvent.identifier());
+ Assertions.assertEquals(GetFunctionPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.GET_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testAlterFunctionEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ FunctionChange change = FunctionChange.updateComment("new comment");
+ dispatcher.alterFunction(identifier, change);
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(AlterFunctionEvent.class, event.getClass());
+ FunctionInfo functionInfo = ((AlterFunctionEvent)
event).updatedFunctionInfo();
+ checkFunctionInfo(functionInfo, function);
+ Assertions.assertEquals(1, ((AlterFunctionEvent)
event).functionChanges().length);
+ Assertions.assertEquals(change, ((AlterFunctionEvent)
event).functionChanges()[0]);
+ Assertions.assertEquals(OperationType.ALTER_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(identifier, preEvent.identifier());
+ Assertions.assertEquals(AlterFunctionPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(1, ((AlterFunctionPreEvent)
preEvent).functionChanges().length);
+ Assertions.assertEquals(change, ((AlterFunctionPreEvent)
preEvent).functionChanges()[0]);
+ Assertions.assertEquals(OperationType.ALTER_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testDropFunctionEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ dispatcher.dropFunction(identifier);
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(DropFunctionEvent.class, event.getClass());
+ Assertions.assertEquals(true, ((DropFunctionEvent) event).isExists());
+ Assertions.assertEquals(OperationType.DROP_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(identifier, preEvent.identifier());
+ Assertions.assertEquals(DropFunctionPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(OperationType.DROP_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testListFunctionEvent() {
+ Namespace namespace = Namespace.of("metalake", "catalog", "schema");
+ dispatcher.listFunctions(namespace);
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(namespace.toString(),
event.identifier().toString());
+ Assertions.assertEquals(ListFunctionEvent.class, event.getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionEvent)
event).namespace());
+ Assertions.assertEquals(OperationType.LIST_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(namespace.toString(),
preEvent.identifier().toString());
+ Assertions.assertEquals(ListFunctionPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionPreEvent)
preEvent).namespace());
+ Assertions.assertEquals(OperationType.LIST_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testListFunctionInfosEvent() {
+ Namespace namespace = Namespace.of("metalake", "catalog", "schema");
+ dispatcher.listFunctionInfos(namespace);
+
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(namespace.toString(),
event.identifier().toString());
+ Assertions.assertEquals(ListFunctionInfosEvent.class, event.getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionInfosEvent)
event).namespace());
+ FunctionInfo[] functionInfos = ((ListFunctionInfosEvent)
event).functionInfos();
+ Assertions.assertEquals(1, functionInfos.length);
+ checkFunctionInfo(functionInfos[0], function);
+ Assertions.assertEquals(OperationType.LIST_FUNCTION_INFOS,
event.operationType());
+ Assertions.assertEquals(OperationStatus.SUCCESS, event.operationStatus());
+
+ PreEvent preEvent = dummyEventListener.popPreEvent();
+ Assertions.assertEquals(namespace.toString(),
preEvent.identifier().toString());
+ Assertions.assertEquals(ListFunctionPreEvent.class, preEvent.getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionPreEvent)
preEvent).namespace());
+ Assertions.assertEquals(OperationType.LIST_FUNCTION,
preEvent.operationType());
+ Assertions.assertEquals(OperationStatus.UNPROCESSED,
preEvent.operationStatus());
+ }
+
+ @Test
+ void testRegisterFunctionFailureEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class,
+ () ->
+ failureDispatcher.registerFunction(
+ identifier,
+ function.comment(),
+ function.functionType(),
+ function.deterministic(),
+ function.definitions()));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(RegisterFunctionFailureEvent.class,
event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class,
+ ((RegisterFunctionFailureEvent) event).exception().getClass());
+ Assertions.assertNotNull(((RegisterFunctionFailureEvent)
event).registerFunctionRequest());
+ Assertions.assertEquals(OperationType.REGISTER_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ @Test
+ void testGetFunctionFailureEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class, () ->
failureDispatcher.getFunction(identifier));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(GetFunctionFailureEvent.class, event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class, ((GetFunctionFailureEvent)
event).exception().getClass());
+ Assertions.assertEquals(OperationType.GET_FUNCTION, event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ @Test
+ void testAlterFunctionFailureEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ FunctionChange change = FunctionChange.updateComment("new comment");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class, () ->
failureDispatcher.alterFunction(identifier, change));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(AlterFunctionFailureEvent.class, event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class,
+ ((AlterFunctionFailureEvent) event).exception().getClass());
+ Assertions.assertEquals(1, ((AlterFunctionFailureEvent)
event).functionChanges().length);
+ Assertions.assertEquals(change, ((AlterFunctionFailureEvent)
event).functionChanges()[0]);
+ Assertions.assertEquals(OperationType.ALTER_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ @Test
+ void testDropFunctionFailureEvent() {
+ NameIdentifier identifier = NameIdentifier.of("metalake", "catalog",
"schema", "func");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class, () ->
failureDispatcher.dropFunction(identifier));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(identifier, event.identifier());
+ Assertions.assertEquals(DropFunctionFailureEvent.class, event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class, ((DropFunctionFailureEvent)
event).exception().getClass());
+ Assertions.assertEquals(OperationType.DROP_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ @Test
+ void testListFunctionFailureEvent() {
+ Namespace namespace = Namespace.of("metalake", "catalog", "schema");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class, () ->
failureDispatcher.listFunctions(namespace));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(namespace.toString(),
event.identifier().toString());
+ Assertions.assertEquals(ListFunctionFailureEvent.class, event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class, ((ListFunctionFailureEvent)
event).exception().getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionFailureEvent)
event).namespace());
+ Assertions.assertEquals(OperationType.LIST_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ @Test
+ void testListFunctionInfosFailureEvent() {
+ Namespace namespace = Namespace.of("metalake", "catalog", "schema");
+ Assertions.assertThrowsExactly(
+ GravitinoRuntimeException.class, () ->
failureDispatcher.listFunctionInfos(namespace));
+ Event event = dummyEventListener.popPostEvent();
+ Assertions.assertEquals(namespace.toString(),
event.identifier().toString());
+ Assertions.assertEquals(ListFunctionFailureEvent.class, event.getClass());
+ Assertions.assertEquals(
+ GravitinoRuntimeException.class, ((ListFunctionFailureEvent)
event).exception().getClass());
+ Assertions.assertEquals(namespace, ((ListFunctionFailureEvent)
event).namespace());
+ Assertions.assertEquals(OperationType.LIST_FUNCTION,
event.operationType());
+ Assertions.assertEquals(OperationStatus.FAILURE, event.operationStatus());
+ }
+
+ private void checkFunctionInfo(FunctionInfo functionInfo, Function func) {
+ Assertions.assertEquals(func.name(), functionInfo.name());
+ Assertions.assertEquals(func.functionType(), functionInfo.functionType());
+ Assertions.assertEquals(func.deterministic(),
functionInfo.deterministic());
+ Assertions.assertEquals(func.comment(), functionInfo.comment());
+ Assertions.assertArrayEquals(func.definitions(),
functionInfo.definitions());
+ Assertions.assertEquals(func.auditInfo(), functionInfo.auditInfo());
+ }
+
+ private Function mockFunction() {
+ Function func = mock(Function.class);
+ when(func.name()).thenReturn("func");
+ when(func.comment()).thenReturn("test function");
+ when(func.functionType()).thenReturn(FunctionType.SCALAR);
+ when(func.deterministic()).thenReturn(true);
+ when(func.definitions()).thenReturn(new FunctionDefinition[0]);
+ when(func.auditInfo()).thenReturn(null);
+ return func;
+ }
+
+ private FunctionDispatcher mockFunctionDispatcher() {
+ FunctionDispatcher dispatcher = mock(FunctionDispatcher.class);
+ when(dispatcher.registerFunction(
+ any(NameIdentifier.class),
+ any(String.class),
+ any(FunctionType.class),
+ any(Boolean.class),
+ any(FunctionDefinition[].class)))
+ .thenReturn(function);
+
when(dispatcher.getFunction(any(NameIdentifier.class))).thenReturn(function);
+ when(dispatcher.dropFunction(any(NameIdentifier.class))).thenReturn(true);
+ when(dispatcher.listFunctions(any(Namespace.class))).thenReturn(null);
+ when(dispatcher.listFunctionInfos(any(Namespace.class))).thenReturn(new
Function[] {function});
+ when(dispatcher.alterFunction(any(NameIdentifier.class),
any(FunctionChange.class)))
+ .thenReturn(function);
+ return dispatcher;
+ }
+
+ private FunctionDispatcher mockExceptionFunctionDispatcher() {
+ FunctionDispatcher dispatcher =
+ mock(
+ FunctionDispatcher.class,
+ invocation -> {
+ throw new GravitinoRuntimeException("Exception for all methods");
+ });
+ return dispatcher;
+ }
+}
diff --git a/docs/gravitino-server-config.md b/docs/gravitino-server-config.md
index 4b938952a6..e01c56ec05 100644
--- a/docs/gravitino-server-config.md
+++ b/docs/gravitino-server-config.md
@@ -193,6 +193,7 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| Gravitino server job operation | `RunJobEvent`, `GetJobEvent`,
`ListJobsEvent`, `CancelJobEvent`, `RunJobFailureEvent`, `GetJobFailureEvent`,
`ListJobsFailureEvent`, `CancelJobFailureEvent`
[...]
| Gravitino server statistics operation | `ListStatisticsEvent`,
`UpdateStatisticsEvent`, `DropStatisticsEvent`, `ListPartitionStatisticsEvent`,
`UpdatePartitionStatisticsEvent`, `DropPartitionStatisticsEvent`,
`ListStatisticsFailureEvent`, `UpdateStatisticsFailureEvent`,
`DropStatisticsFailureEvent`, `ListPartitionStatisticsFailureEvent`,
`UpdatePartitionStatisticsFailureEvent`, `DropPartitionStatisticsFailureEvent`
[...]
| policy operation | `CreatePolicyEvent`,
`AlterPolicyEvent`, `DeletePolicyEvent`, `GetPolicyEvent`, `ListPoliciesEvent`,
`AssociatePoliciesForMetadataObjectEvent`,
`ListAssociatedPoliciesForMetadataObjectEvent`, `CreatePolicyFailureEvent`,
`AlterPolicyFailureEvent`, `DeletePolicyFailureEvent`, `GetPolicyFailureEvent`,
`ListPoliciesFailureEvent`, `AssociatePoliciesForMetadataObjectFailureEvent`,
`ListAssociatedPoliciesForMetadataObjectFailureEvent` | 1.1.0 |
+| function operation | `RegisterFunctionEvent`,
`GetFunctionEvent`, `AlterFunctionEvent`, `DropFunctionEvent`,
`ListFunctionEvent`, `ListFunctionInfosEvent`, `RegisterFunctionFailureEvent`,
`GetFunctionFailureEvent`, `AlterFunctionFailureEvent`,
`DropFunctionFailureEvent`, `ListFunctionFailureEvent`
| 1.3.0 |
##### Pre-event
@@ -217,6 +218,7 @@ Gravitino triggers a pre-event before the operation, a
post-event after the comp
| Gravitino server job operation | `RunJobPreEvent`,
`GetJobPreEvent`, `ListJobsPreEvent`, `CancelJobPreEvent`
| 1.0.1 |
| Gravitino server statistics operation | `ListStatisticsPreEvent`,
`UpdateStatisticsPreEvent`, `DropStatisticsPreEvent`,
`ListPartitionStatisticsPreEvent`, `UpdatePartitionStatisticsPreEvent`,
`DropPartitionStatisticsPreEvent`
| 1.1.0 |
| policy operation | `CreatePolicyPreEvent`,
`AlterPolicyPreEvent`, `DeletePolicyPreEvent`, `GetPolicyPreEvent`,
`ListPoliciesPreEvent`, `AssociatePoliciesForMetadataObjectPreEvent`,
`ListAssociatedPoliciesForMetadataObjectPreEvent`
| 1.1.0 |
+| function operation | `RegisterFunctionPreEvent`,
`GetFunctionPreEvent`, `AlterFunctionPreEvent`, `DropFunctionPreEvent`,
`ListFunctionPreEvent`
| 1.3.0 |
#### Event listener plugin