fix: Added projection for page call that only needs application id details (#19273)

The NewPage document contains DSL details for a page as well. When we
don't need this information, we can use a projection that disables this
field. User was facing a problem with this call taking 12 seconds to
complete with those details. (document is 1 MB in size for them)
This commit is contained in:
Nidhi 2022-12-28 16:24:32 +05:30 committed by GitHub
parent a70ca2bc01
commit 51f18af87f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 41 additions and 12 deletions

View File

@ -43,8 +43,8 @@ public class PageControllerCE {
@Autowired
public PageControllerCE(ApplicationPageService applicationPageService,
NewPageService newPageService,
CreateDBTablePageSolution createDBTablePageSolution
NewPageService newPageService,
CreateDBTablePageSolution createDBTablePageSolution
) {
this.applicationPageService = applicationPageService;
this.newPageService = newPageService;
@ -122,9 +122,10 @@ public class PageControllerCE {
* In case the page has never been published, the page gets deleted.
* In case the page has been published, this page would eventually get deleted whenever the application is published
* next.
*
* @param defaultPageId defaultPageId which will be needed to find the actual page that needs to be deleted
* @param branchName git branch to find the exact page which needs to be deleted
* @return deleted page DTO
* @return deleted page DTO
*/
@DeleteMapping("/{defaultPageId}")
public Mono<ResponseDTO<PageDTO>> deletePage(@PathVariable String defaultPageId,
@ -155,10 +156,11 @@ public class PageControllerCE {
* If Application ID is present, it'll fetch all pages of that application in the provided mode.
* if Page ID is present, it'll fetch all pages of the corresponding Application.
* If both IDs are present, it'll use the Application ID only and ignore the Page ID
*
* @param applicationId Id of the application
* @param pageId id of a page
* @param mode In which mode it's in
* @param branchName name of the current branch
* @param pageId id of a page
* @param mode In which mode it's in
* @param branchName name of the current branch
* @return List of ApplicationPagesDTO along with other meta data
*/
@GetMapping
@ -166,6 +168,7 @@ public class PageControllerCE {
@RequestParam(required = false) String pageId,
@RequestParam(required = true, defaultValue = "EDIT") ApplicationMode mode,
@RequestHeader(name = FieldName.BRANCH_NAME, required = false) String branchName) {
log.debug("Going to fetch applicationPageDTO for applicationId: {}, pageId: {}, branchName: {}, mode: {}", applicationId, pageId, branchName, mode);
return newPageService.findApplicationPages(applicationId, pageId, branchName, mode)
.map(resources -> new ResponseDTO<>(HttpStatus.OK.value(), resources, null));
}

View File

@ -27,4 +27,6 @@ public interface CustomNewPageRepositoryCE extends AppsmithRepository<NewPage> {
Mono<NewPage> findPageByBranchNameAndDefaultPageId(String branchName, String defaultPageId, AclPermission permission);
Flux<NewPage> findSlugsByApplicationIds(List<String> applicationIds, AclPermission aclPermission);
Mono<NewPage> findRootApplicationIdById(String defaultPageId, AclPermission readPermission);
}

View File

@ -5,7 +5,10 @@ import com.appsmith.server.constants.FieldName;
import com.appsmith.server.domains.NewPage;
import com.appsmith.server.domains.QLayout;
import com.appsmith.server.domains.QNewPage;
import com.appsmith.server.domains.User;
import com.appsmith.server.dtos.PageDTO;
import com.appsmith.server.exceptions.AppsmithError;
import com.appsmith.server.exceptions.AppsmithException;
import com.appsmith.server.repositories.BaseAppsmithRepositoryImpl;
import com.appsmith.server.repositories.CacheableRepositoryHelper;
import lombok.extern.slf4j.Slf4j;
@ -13,6 +16,7 @@ import org.springframework.data.mongodb.core.ReactiveMongoOperations;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@ -43,6 +47,27 @@ public class CustomNewPageRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Ne
return queryAll(List.of(applicationIdCriteria, activeEditModeCriteria), aclPermission);
}
@Override
public Mono<NewPage> findRootApplicationIdById(String id, AclPermission permission) {
if (id == null) {
return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ID));
}
return ReactiveSecurityContextHolder.getContext()
.map(ctx -> ctx.getAuthentication())
.map(auth -> auth.getPrincipal())
.flatMap(principal -> getAllPermissionGroupsForUser((User) principal))
.flatMap(permissionGroups -> {
Query query = new Query(getIdCriteria(id));
query.fields().include(FieldName.APPLICATION_ID, FieldName.DEFAULT_RESOURCES);
query.addCriteria(new Criteria().andOperator(notDeleted(), userAcl(permissionGroups, permission)));
return mongoOperations.query(this.genericDomain)
.matching(query)
.one()
.flatMap(obj -> setUserPermissionsInObject(obj, permissionGroups));
});
}
@Override
public Mono<NewPage> findByIdAndLayoutsIdAndViewMode(String id, String layoutId, AclPermission aclPermission, Boolean viewMode) {
String layoutsIdKey;
@ -58,7 +83,7 @@ public class CustomNewPageRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Ne
layoutsKey = fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.layouts);
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
Criteria deletedCriterion = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
Criteria deletedCriterion = where(fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
criteria.add(deletedCriterion);
}
layoutsIdKey = layoutsKey + "." + fieldName(QLayout.layout.id);
@ -79,7 +104,7 @@ public class CustomNewPageRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Ne
if (Boolean.FALSE.equals(viewMode)) {
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
Criteria deletedCriterion = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
Criteria deletedCriterion = where(fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
criteria.add(deletedCriterion);
}
@ -99,7 +124,7 @@ public class CustomNewPageRepositoryCEImpl extends BaseAppsmithRepositoryImpl<Ne
if (Boolean.FALSE.equals(viewMode)) {
// In case a page has been deleted in edit mode, but still exists in deployed mode, NewPage object would exist. To handle this, only fetch non-deleted pages
Criteria deletedCriteria = where (fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
Criteria deletedCriteria = where(fieldName(QNewPage.newPage.unpublishedPage) + "." + fieldName(QNewPage.newPage.unpublishedPage.deletedAt)).is(null);
criteria.add(deletedCriteria);
}

View File

@ -46,8 +46,6 @@ import java.util.Set;
import java.util.stream.Collectors;
import static com.appsmith.external.helpers.AppsmithBeanUtils.copyNewFieldValuesIntoOldObject;
import static com.appsmith.server.acl.AclPermission.MANAGE_PAGES;
import static com.appsmith.server.acl.AclPermission.READ_PAGES;
import static com.appsmith.server.exceptions.AppsmithError.INVALID_PARAMETER;
@ -545,7 +543,7 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
if (!StringUtils.hasLength(defaultPageId)) {
return Mono.error(new AppsmithException(INVALID_PARAMETER, FieldName.PAGE_ID, defaultPageId));
}
getPageMono = repository.findById(defaultPageId, pagePermission.getReadPermission());
getPageMono = repository.findRootApplicationIdById(defaultPageId, pagePermission.getReadPermission());
} else {
getPageMono = repository.findPageByBranchNameAndDefaultPageId(branchName, defaultPageId, pagePermission.getReadPermission());
}
@ -554,6 +552,7 @@ public class NewPageServiceCEImpl extends BaseService<NewPageRepository, NewPage
new AppsmithException(AppsmithError.NO_RESOURCE_FOUND, FieldName.PAGE_ID, defaultPageId + ", " + branchName))
)
.map(newPage -> {
log.debug("Retrieved possible application ids for page, picking the appropriate one now");
if (newPage.getDefaultResources() != null) {
return newPage.getDefaultResources().getApplicationId();
} else {