mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) speed up a step in document deletion
Summary: The `_repairWorkspaceGuests` method is slow for workspaces with large numbers of documents. It makes a query that produces a lot of rows. The query itself is tolerable, but TypeORM processing uses enough CPU to be a likely culprit in some production instability. This diff splits the query into two pieces that are logically independent, but which when combined were resulting in the number of rows being the product of the two pieces. Once split, there is also a where clause that can be applied to one of the pieces. The purpose of the method is to add every user that a document within a workspace is shared with to a "guest" group of the workspace itself. The design of "guest" groups is not ideal, but this diff leaves the design unchanged and is intended only to speed up operation. Made some small tweaks to the timing of a flakey test, and temporarily recreated the `samples` directory removed in a previous diff (this is currently breaking tests badly on a fresh worker without a `samples` directory lying around) Test Plan: added test; existing tests pass Reviewers: jarek Reviewed By: jarek Differential Revision: https://phab.getgrist.com/D2844
This commit is contained in:
@@ -2420,20 +2420,27 @@ export class HomeDBManager extends EventEmitter {
|
||||
*/
|
||||
private async _repairWorkspaceGuests(scope: Scope, wsId: number, transaction?: EntityManager): Promise<void> {
|
||||
return await this._runInTransaction(transaction, async manager => {
|
||||
// Get guest group for workspace.
|
||||
const wsQuery = this._workspace(scope, wsId, {manager})
|
||||
.leftJoinAndSelect('workspaces.aclRules', 'acl_rules')
|
||||
.leftJoinAndSelect('acl_rules.group', 'groups')
|
||||
.leftJoinAndSelect('workspaces.docs', 'docs')
|
||||
.leftJoinAndSelect('docs.aclRules', 'doc_acl_rules')
|
||||
.leftJoinAndSelect('doc_acl_rules.group', 'doc_groups')
|
||||
.leftJoinAndSelect('doc_groups.memberUsers', 'doc_users');
|
||||
const workspace: Workspace = (await wsQuery.getOne())!;
|
||||
.leftJoinAndSelect('acl_rules.group', 'groups');
|
||||
const workspace: Workspace = (await wsQuery.getOne())!;
|
||||
const wsGuestGroup = workspace.aclRules.map(aclRule => aclRule.group)
|
||||
.find(_grp => _grp.name === roles.GUEST);
|
||||
if (!wsGuestGroup) {
|
||||
throw new Error(`_repairWorkspaceGuests error: could not find ${roles.GUEST} ACL group`);
|
||||
}
|
||||
wsGuestGroup.memberUsers = this._filterEveryone(getResourceUsers(workspace.docs));
|
||||
|
||||
// Get explicitly added users of docs inside the workspace, as a separate query
|
||||
// to avoid multiplying rows and to allow filtering the result in sql.
|
||||
const wsWithDocsQuery = this._workspace(scope, wsId, {manager})
|
||||
.leftJoinAndSelect('workspaces.docs', 'docs')
|
||||
.leftJoinAndSelect('docs.aclRules', 'doc_acl_rules')
|
||||
.leftJoinAndSelect('doc_acl_rules.group', 'doc_groups')
|
||||
.leftJoinAndSelect('doc_groups.memberUsers', 'doc_users')
|
||||
.andWhere('doc_users.id is not null');
|
||||
const wsWithDocs = await wsWithDocsQuery.getOne();
|
||||
wsGuestGroup.memberUsers = this._filterEveryone(getResourceUsers(wsWithDocs?.docs || []));
|
||||
await manager.save(wsGuestGroup);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user