From 8d39c8f9a0c211cffe3eaa040fff7bb0d95d0c5a Mon Sep 17 00:00:00 2001 From: HiranyaKavishani Date: Thu, 15 Aug 2024 16:55:12 +0530 Subject: [PATCH] Fixing gateway timeout issue in API Subscription retrieval with high #of APIs (#6737) --- .../utils/RegistryPersistenceUtil.java | 130 ++++++++++-------- 1 file changed, 71 insertions(+), 59 deletions(-) diff --git a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java index bda9ce68da7b..989b42b36a17 100644 --- a/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java +++ b/components/apimgt/org.wso2.carbon.apimgt.persistence/src/main/java/org/wso2/carbon/apimgt/persistence/utils/RegistryPersistenceUtil.java @@ -86,11 +86,15 @@ import java.util.Map; import java.util.Properties; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; public class RegistryPersistenceUtil { private static final Log log = LogFactory.getLog(RegistryPersistenceUtil.class); + //Stores to load RXTs only once + private static final ConcurrentHashMap tenantRxtLoaded = new ConcurrentHashMap<>(); + /** * When an input is having '-AT-',replace it with @ [This is required to persist API data between registry and database] * @@ -446,76 +450,84 @@ public static void loadTenantRegistry(int tenantId) throws RegistryException { } public static void loadloadTenantAPIRXT(String tenant, int tenantID) throws RegistryException, PersistenceException { - - RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService(); - UserRegistry registry = null; - try { - - registry = registryService.getGovernanceSystemRegistry(tenantID); - } catch (RegistryException e) { - throw new PersistenceException("Error when create registry instance ", e); - } - - String rxtDir = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "resources" - + File.separator + "rxts"; - File file = new File(rxtDir); - FilenameFilter filenameFilter = new FilenameFilter() { - @Override public boolean accept(File dir, String name) { - // if the file extension is .rxt return true, else false - return name.endsWith(".rxt"); + // Synchronize on the tenant specific lock + synchronized (tenantID + "_loadTenantAPIRXT") { + // Check if RXTs have already been loaded for this tenant + if (Boolean.TRUE.equals(tenantRxtLoaded.get(tenantID))) { + return; // RXTs already loaded, exit method } - }; - String[] rxtFilePaths = file.list(filenameFilter); - - if (rxtFilePaths == null) { - throw new PersistenceException("rxt files not found in directory " + rxtDir); - } + RegistryService registryService = ServiceReferenceHolder.getInstance().getRegistryService(); + UserRegistry registry = null; + try { - for (String rxtPath : rxtFilePaths) { - String resourcePath = GovernanceConstants.RXT_CONFIGS_PATH + RegistryConstants.PATH_SEPARATOR + rxtPath; + registry = registryService.getGovernanceSystemRegistry(tenantID); + } catch (RegistryException e) { + throw new PersistenceException("Error when create registry instance ", e); + } - //This is "registry" is a governance registry instance, therefore calculate the relative path to governance. - String govRelativePath = RegistryUtils.getRelativePathToOriginal(resourcePath, - RegistryPersistenceUtil.getMountedPath(RegistryContext.getBaseInstance(), - RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH)); - try { - // calculate resource path - UserRealm tenantUserRealm = (UserRealm) ServiceReferenceHolder.getInstance().getRealmService().getTenantUserRealm(tenantID); - RegistryAuthorizationManager authorizationManager = new RegistryAuthorizationManager(tenantUserRealm); - resourcePath = authorizationManager.computePathOnMount(resourcePath); + String rxtDir = CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "resources" + + File.separator + "rxts"; + File file = new File(rxtDir); + FilenameFilter filenameFilter = new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + // if the file extension is .rxt return true, else false + return name.endsWith(".rxt"); + } + }; + String[] rxtFilePaths = file.list(filenameFilter); - org.wso2.carbon.user.api.AuthorizationManager authManager = ServiceReferenceHolder.getInstance() - .getRealmService(). - getTenantUserRealm(tenantID) - .getAuthorizationManager(); + if (rxtFilePaths == null) { + throw new PersistenceException("rxt files not found in directory " + rxtDir); + } - if (registry.resourceExists(govRelativePath)) { - // set anonymous user permission to RXTs - if (!authManager.isRoleAuthorized(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET)) { - authManager.authorizeRole(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET); + for (String rxtPath : rxtFilePaths) { + String resourcePath = GovernanceConstants.RXT_CONFIGS_PATH + RegistryConstants.PATH_SEPARATOR + rxtPath; + + //This is "registry" is a governance registry instance, therefore calculate the relative path to governance. + String govRelativePath = RegistryUtils.getRelativePathToOriginal(resourcePath, + RegistryPersistenceUtil.getMountedPath(RegistryContext.getBaseInstance(), + RegistryConstants.GOVERNANCE_REGISTRY_BASE_PATH)); + try { + // calculate resource path + UserRealm tenantUserRealm = (UserRealm) ServiceReferenceHolder.getInstance().getRealmService().getTenantUserRealm(tenantID); + RegistryAuthorizationManager authorizationManager = new RegistryAuthorizationManager(tenantUserRealm); + resourcePath = authorizationManager.computePathOnMount(resourcePath); + + org.wso2.carbon.user.api.AuthorizationManager authManager = ServiceReferenceHolder.getInstance() + .getRealmService(). + getTenantUserRealm(tenantID) + .getAuthorizationManager(); + + if (registry.resourceExists(govRelativePath)) { + // set anonymous user permission to RXTs + if (!authManager.isRoleAuthorized(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET)) { + authManager.authorizeRole(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET); + } + continue; } - continue; - } - String rxt = FileUtil.readFileToString(rxtDir + File.separator + rxtPath); - Resource resource = registry.newResource(); - resource.setContent(rxt.getBytes(Charset.defaultCharset())); - resource.setMediaType(APIConstants.RXT_MEDIA_TYPE); - registry.put(govRelativePath, resource); + String rxt = FileUtil.readFileToString(rxtDir + File.separator + rxtPath); + Resource resource = registry.newResource(); + resource.setContent(rxt.getBytes(Charset.defaultCharset())); + resource.setMediaType(APIConstants.RXT_MEDIA_TYPE); + registry.put(govRelativePath, resource); - authManager.authorizeRole(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET); + authManager.authorizeRole(APIConstants.ANONYMOUS_ROLE, resourcePath, ActionConstants.GET); - } catch (UserStoreException e) { - throw new PersistenceException("Error while adding role permissions to API", e); - } catch (IOException e) { - String msg = "Failed to read rxt files"; - throw new PersistenceException(msg, e); - } catch (RegistryException e) { - String msg = "Failed to add rxt to registry "; - throw new PersistenceException(msg, e); + } catch (UserStoreException e) { + throw new PersistenceException("Error while adding role permissions to API", e); + } catch (IOException e) { + String msg = "Failed to read rxt files"; + throw new PersistenceException(msg, e); + } catch (RegistryException e) { + String msg = "Failed to add rxt to registry "; + throw new PersistenceException(msg, e); + } } + // Mark RXTs as loaded for this tenant + tenantRxtLoaded.put(tenantID, Boolean.TRUE); } - } /**