Copilot commented on code in PR #11057:
URL: https://github.com/apache/gravitino/pull/11057#discussion_r3226361746


##########
plugins/idp-basic/src/main/java/org/apache/gravitino/storage/provider/IdpBasicUserMetaProvider.java:
##########
@@ -0,0 +1,125 @@
+/*
+ * 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.storage.provider;
+
+import com.google.common.base.Preconditions;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import org.apache.gravitino.storage.relational.mapper.IdpGroupUserRelMapper;
+import org.apache.gravitino.storage.relational.mapper.IdpUserMetaMapper;
+import org.apache.gravitino.storage.relational.po.IdpUserPO;
+import org.apache.gravitino.storage.relational.service.IdpUserMetaService;
+import org.apache.gravitino.storage.relational.utils.SessionUtils;
+
+/** The provider class for user metadata. It provides the basic database 
operations for user. */
+public class IdpBasicUserMetaProvider implements IdpUserMetaService<IdpUserPO> 
{
+  private static final IdpBasicUserMetaProvider INSTANCE = new 
IdpBasicUserMetaProvider();
+
+  public static IdpBasicUserMetaProvider getInstance() {
+    return INSTANCE;
+  }
+
+  public IdpBasicUserMetaProvider() {}
+
+  @Override
+  public Optional<IdpUserPO> findUser(String userName) {
+    return Optional.ofNullable(
+        SessionUtils.getWithoutCommit(
+            IdpUserMetaMapper.class, mapper -> 
mapper.selectIdpUser(userName)));
+  }
+
+  @Override
+  public List<IdpUserPO> findUsers(List<String> userNames) {
+    if (userNames.isEmpty()) {
+      return Collections.emptyList();
+    }
+
+    return SessionUtils.getWithoutCommit(
+        IdpUserMetaMapper.class, mapper -> mapper.selectIdpUsers(userNames));

Review Comment:
   `findUsers` calls `userNames.isEmpty()` without guarding against `userNames 
== null`, which will throw a NullPointerException. Either validate the argument 
(e.g., require non-null) or treat null the same as an empty list and return 
`Collections.emptyList()` so callers don’t crash unexpectedly.



##########
core/src/main/java/org/apache/gravitino/storage/relational/service/IdpUserMetaService.java:
##########
@@ -0,0 +1,113 @@
+/*
+ * 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.storage.relational.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
+
+/** Core service contract for built-in IdP user metadata operations. */
+public interface IdpUserMetaService<U> {
+  /**
+   * Returns the IdP user metadata service implementation from the runtime 
classpath.
+   *
+   * @param <U> the user metadata type
+   * @return the service implementation
+   */
+  @SuppressWarnings("unchecked")
+  static <U> IdpUserMetaService<U> getInstance() {
+    return (IdpUserMetaService<U>) loadService();
+  }

Review Comment:
   `getInstance()` calls `ServiceLoader.load(...)` every time it’s invoked, 
which can be relatively expensive and may create multiple provider instances 
over time. Consider caching the resolved singleton provider (e.g., a 
lazy-initialized static/holder) since the contract expects exactly one 
implementation on the classpath.



##########
core/src/main/java/org/apache/gravitino/storage/relational/JDBCBackend.java:
##########
@@ -465,10 +467,18 @@ public int hardDeleteLegacyData(Entity.EntityType 
entityType, long legacyTimelin
         return UserMetaService.getInstance()
             .deleteUserMetasByLegacyTimeline(
                 legacyTimeline, GARBAGE_COLLECTOR_SINGLE_DELETION_LIMIT);
+      case IDP_USER:
+        return IdpUserMetaService.getInstance()
+            .deleteUserMetasByLegacyTimeline(
+                legacyTimeline, GARBAGE_COLLECTOR_SINGLE_DELETION_LIMIT);
       case GROUP:
         return GroupMetaService.getInstance()
             .deleteGroupMetasByLegacyTimeline(
                 legacyTimeline, GARBAGE_COLLECTOR_SINGLE_DELETION_LIMIT);
+      case IDP_GROUP:
+        return IdpGroupMetaService.getInstance()
+            .deleteGroupMetasByLegacyTimeline(
+                legacyTimeline, GARBAGE_COLLECTOR_SINGLE_DELETION_LIMIT);

Review Comment:
   `hardDeleteLegacyData` now calls `IdpUserMetaService.getInstance()` / 
`IdpGroupMetaService.getInstance()` for the new entity types. If the idp-basic 
plugin isn’t present on the runtime classpath, these will throw and the garbage 
collector will log an error on every sweep for `IDP_USER`/`IDP_GROUP`. Consider 
handling `IllegalStateException` here (return 0 / skip) or ensuring provider 
presence is validated once at startup to avoid repeated error logs.



##########
core/src/main/java/org/apache/gravitino/storage/relational/service/IdpGroupMetaService.java:
##########
@@ -0,0 +1,123 @@
+/*
+ * 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.storage.relational.service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.ServiceLoader;
+
+/** Core service contract for built-in IdP group metadata operations. */
+public interface IdpGroupMetaService<G, R> {
+
+  /**
+   * Returns the IdP group metadata service implementation from the runtime 
classpath.
+   *
+   * @param <G> the group metadata type
+   * @param <R> the group-user relation metadata type
+   * @return the service implementation
+   */
+  @SuppressWarnings("unchecked")
+  static <G, R> IdpGroupMetaService<G, R> getInstance() {
+    return (IdpGroupMetaService<G, R>) loadService();
+  }

Review Comment:
   `getInstance()` calls `ServiceLoader.load(...)` on each invocation, which 
can be unnecessarily expensive and may lead to repeated provider instantiation. 
Since the design requires exactly one `IdpGroupMetaService` implementation, 
consider caching the resolved provider in a static/holder so callers reuse it.



##########
plugins/idp-basic/src/main/java/org/apache/gravitino/storage/provider/IdpBasicGroupMetaProvider.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.storage.provider;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import org.apache.gravitino.storage.relational.mapper.IdpGroupMetaMapper;
+import org.apache.gravitino.storage.relational.mapper.IdpGroupUserRelMapper;
+import org.apache.gravitino.storage.relational.po.IdpGroupPO;
+import org.apache.gravitino.storage.relational.po.IdpGroupUserRelPO;
+import org.apache.gravitino.storage.relational.service.IdpGroupMetaService;
+import org.apache.gravitino.storage.relational.utils.SessionUtils;
+
+/** The provider class for group metadata. It provides the basic database 
operations for group. */
+public class IdpBasicGroupMetaProvider
+    implements IdpGroupMetaService<IdpGroupPO, IdpGroupUserRelPO> {
+  private static final IdpBasicGroupMetaProvider INSTANCE = new 
IdpBasicGroupMetaProvider();
+
+  public static IdpBasicGroupMetaProvider getInstance() {
+    return INSTANCE;
+  }
+
+  public IdpBasicGroupMetaProvider() {}
+
+  @Override
+  public Optional<IdpGroupPO> findGroup(String groupName) {
+    return Optional.ofNullable(
+        SessionUtils.getWithoutCommit(
+            IdpGroupMetaMapper.class, mapper -> 
mapper.selectIdpGroup(groupName)));
+  }
+
+  @Override
+  public List<String> listUserNames(String groupName) {
+    Optional<IdpGroupPO> group = findGroup(groupName);
+    if (!group.isPresent()) {
+      return Collections.emptyList();
+    }
+
+    return SessionUtils.getWithoutCommit(
+        IdpGroupUserRelMapper.class,
+        mapper -> mapper.selectUserNamesByGroupId(group.get().getGroupId()));
+  }
+
+  @Override
+  public void createGroup(IdpGroupPO groupPO) {
+    SessionUtils.doWithCommit(IdpGroupMetaMapper.class, mapper -> 
mapper.insertIdpGroup(groupPO));
+  }
+
+  @Override
+  public boolean deleteGroup(IdpGroupPO groupPO, Long deletedAt) {
+    SessionUtils.doMultipleWithCommit(
+        () ->
+            SessionUtils.doWithoutCommit(
+                IdpGroupMetaMapper.class,
+                mapper -> mapper.softDeleteIdpGroup(groupPO.getGroupId(), 
deletedAt)),
+        () ->
+            SessionUtils.doWithoutCommit(
+                IdpGroupUserRelMapper.class,
+                mapper -> 
mapper.softDeleteGroupUsersByGroupId(groupPO.getGroupId(), deletedAt)));
+    return true;
+  }
+
+  @Override
+  public List<Long> selectRelatedUserIds(Long groupId, List<Long> userIds) {
+    return SessionUtils.getWithoutCommit(
+        IdpGroupUserRelMapper.class, mapper -> 
mapper.selectRelatedUserIds(groupId, userIds));
+  }
+
+  @Override
+  public void addUsersToGroup(List<IdpGroupUserRelPO> relations) {
+    if (relations.isEmpty()) {
+      return;
+    }
+    SessionUtils.doWithCommit(
+        IdpGroupUserRelMapper.class, mapper -> 
mapper.batchInsertIdpGroupUsers(relations));
+  }
+
+  @Override
+  public void removeUsersFromGroup(Long groupId, List<Long> userIds, Long 
deletedAt) {
+    if (userIds.isEmpty()) {
+      return;
+    }
+
+    SessionUtils.doWithCommit(
+        IdpGroupUserRelMapper.class,
+        mapper -> mapper.softDeleteIdpGroupUsers(groupId, userIds, deletedAt));

Review Comment:
   `removeUsersFromGroup` calls `userIds.isEmpty()` without guarding against 
`userIds == null`, which will throw a NullPointerException. Either validate the 
argument (require non-null) or treat null as a no-op/empty input to match the 
SQL provider’s ability to handle null lists safely.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to