RANGER-3899: Policy creation/updation takes more time when there are more users,groups,roles#962
RANGER-3899: Policy creation/updation takes more time when there are more users,groups,roles#962ramackri wants to merge 2 commits into
Conversation
…more users,groups,roles
| } | ||
| } | ||
|
|
||
| public Map<String, XXResourceDef> findXXResourceDefsByNameAndPolicyId(Set<String> names, Long policyId) { |
There was a problem hiding this comment.
The caller of findXXResourceDefsByNameAndPolicyId() only needs resourceId (XXResourceDef.id) for each resource name. Retrieving only id from the database will help improve the performance.
- I suggest updating & renaming the method from:
public Map<String, XXResourceDef> findXXResourceDefsByNameAndPolicyId(Set<String> names, Long policyId)
to:
public Map<String, Long> findResourceDefIdsByNameAndPolicyId(Set<String> names, Long policyId)
-
Update the named query
XXResourceDef.findByNamesAndPolicyIdto returnidinstead ofXXResourceDef. -
Review similar updates to following named queries and corresponding Dao methods that use them:
XXAccessTypeDef.findByNamesAndServiceIdXXPolicyConditionDef.findByServiceDefIdAndNamesXXDataMaskTypeDef.findByNamesAndServiceId
| public Map<String, XXResourceDef> findXXResourceDefsByNameAndPolicyId(Set<String> names, Long policyId) { | ||
| Map<String, XXResourceDef> ret = Collections.emptyMap(); | ||
| if (policyId == null || CollectionUtils.isEmpty(names)) { | ||
| return ret; |
There was a problem hiding this comment.
Consider having a single return statement in a method.
| .setParameter("policyId", policyId) | ||
| .getResultList(); | ||
|
|
||
| Map<String, Long> userNameIdMap = new HashMap<>(); |
There was a problem hiding this comment.
To be consistent, consider using streams to convert results ito userNameIdMap - similar to XXRoleDao.getIdsByRoleNames().
| .setParameter("policyId", policyId) | ||
| .getResultList(); | ||
|
|
||
| Map<String, Long> roleNameIdMap = new HashMap<>(); |
There was a problem hiding this comment.
To be consistent, consider using streams to convert results ito roleNameIdMap - similar to XXRoleDao.getIdsByRoleNames().
| .setParameter("policyId", policyId) | ||
| .getResultList(); | ||
|
|
||
| Map<String, Long> groupNameIdMap = new HashMap<>(); |
There was a problem hiding this comment.
To be consistent, consider using streams to convert results ito groupNameIdMap - similar to XXRoleDao.getIdsByRoleNames().
| .collect(Collectors.toSet()); | ||
| Map<String, Long> roleNameIdMap = daoMgr.getXXRole().getIdsByRoleNames(filteredRoleNames); | ||
| for (String roleName : filteredRoleNames) { | ||
| PolicyPrincipalAssociator associator = new PolicyPrincipalAssociator(PRINCIPAL_TYPE.ROLE, roleName, xPolicy, roleNameIdMap.get(roleName), null, null, xPolRoles); |
There was a problem hiding this comment.
Instead of having PolicyPrincipalAssociator take 3 collection parameters and populating one of them in doAssociate() call, consider:
- creating 3 classes
PolicyRoleAssociator,PolicyGroupAssociatorandPolicyUserAssociator - add method
getPolicyRef()to return XXPolicyRefRole/XXPolicyRefGroup/XXPolicyRefUser when the policy exists - add method
createPolicyRef()to create XXPolicyRefRole/XXPolicyRefGroup/XXPolicyRefUser when the policy exists
Long roleId = roleNameIdMap.get(roleName);
PolicyRoleAssociator associator = new PolicyRoleAssociator(roleName, roleId, xPolicy);
if (roleId != null) {
XXPolicyRoleRef roleRef = associator.getPolicyRef();
if (roleRef != null) {
xPolRoles.add(roleRef);
}
} else if (createPrincipalsIfAbsent) {
rangerTransactionSynchronizationAdapter.executeOnTransactionCommit(associator);
} else {
VXResponse gjResponse = new VXResponse();
...
throw restErrorUtil.generateRESTException(gjResponse);
}
Review handling of groups and users references as well - line 243 and 268.
| XXPolicyRefRoleDao xxPolicyRefRoleDao = daoMgr.getXXPolicyRefRole(); | ||
| XXPolicyRefGroupDao xxPolicyRefGroupDao = daoMgr.getXXPolicyRefGroup(); | ||
|
|
||
| Map<String, Long> policyUserNameIdMap = xPolicyRefUserDao.findUserNameIdByPolicyId(policyId); |
There was a problem hiding this comment.
Consider moving lines 386, 387 and 388 into cleanupPolicyRefUsers(), cleanupPolicyRefRoles() and cleanupPolicyRefGroups() respectively - to improve readability.
What changes were proposed in this pull request?
Optimized
PolicyRefUpdaterand related DAOs so policy create/update performs fewer database round-trips when a policy references many users, groups, and roles.Problem
When creating or updating a policy with a large number of principals (users, groups, roles), Ranger Admin was slow because:
findByUserName,findByGroupName,findByRoleName, etc.).cleanupRefTables()deleted all rows fromx_policy_ref_user,x_policy_ref_group, andx_policy_ref_role(and other ref tables), then re-inserted every principal even when nothing changed.Changes
Batch lookups via named queries — Added
IN (:names)JPA named queries and DAO helpers to resolve principals and definitions in bulk:XXUser.getIdsByUserNamesXXGroup.getIdsByGroupNamesXXRole.getIdsByRoleNamesXXResourceDef.findByNamesAndPolicyIdXXAccessTypeDef.findByNamesAndServiceIdXXPolicyConditionDef.findByServiceDefIdAndNamesXXDataMaskTypeDef.findByNamesAndServiceIdPre-resolved principal IDs —
PolicyPrincipalAssociatornow accepts a pre-fetched principal ID from the bulk map, avoiding per-name lookups when the principal already exists.Selective cleanup on policy update — Introduced
cleanupRefTablesForUpdate()that:Unified create/update flow —
createNewPolMappingForRefTable()takes a newisCleanupRefTablesNeededflag:false(no prior ref rows)true(runs selective cleanup before insert)ServiceDBStoreno longer callscleanupRefTables()separately before mappingBatch insert helper — Added
batchInsert()with bulk-mode handling and debug timing logs arounddao.batchCreate().Files changed (15)
PolicyRefUpdater.java,ServiceDBStore.javaXXUserDao,XXGroupDao,XXRoleDao,XXResourceDefDao,XXAccessTypeDefDao,XXPolicyConditionDefDao,XXDataMaskTypeDefDao,XXPolicyRefUserDao,XXPolicyRefGroupDao,XXPolicyRefRoleDaojpa_named_queries.xmlTestPolicyRefUpdater.java,TestServiceDBStore.javaHow was this patch tested?
Unit tests
TestPolicyRefUpdaterfor the new bulk-lookup APIs andisCleanupRefTablesNeededparametertestCleanupRefTablesForUpdate_SelectivePrincipalCleanupto verify selective delete/insert for users, roles, and groups on updateTestServiceDBStorefor the newcreateNewPolMappingForRefTablesignaturemvn -pl security-admin test -Dtest=TestPolicyRefUpdater,TestServiceDBStore