mirror of
https://github.com/outline/outline.git
synced 2026-06-13 03:14:59 +03:00
perf: Move recalculation of memberships to async job (#9567)
* perf: Move recalculation of memberships to async job * tsc
This commit is contained in:
@@ -1,15 +1,7 @@
|
||||
import { Transaction } from "sequelize";
|
||||
import { createContext } from "@server/context";
|
||||
import { traceFunction } from "@server/logging/tracing";
|
||||
import {
|
||||
User,
|
||||
Document,
|
||||
Collection,
|
||||
Pin,
|
||||
Event,
|
||||
UserMembership,
|
||||
GroupMembership,
|
||||
} from "@server/models";
|
||||
import { User, Document, Collection, Pin, Event } from "@server/models";
|
||||
|
||||
type Props = {
|
||||
/** User attempting to move the document */
|
||||
@@ -227,44 +219,6 @@ async function documentMover({
|
||||
await document.save({ transaction });
|
||||
result.documents.push(document);
|
||||
|
||||
// If there are any sourced memberships for this document, we need to go to the source
|
||||
// memberships and recalculate the membership for the user or group.
|
||||
const [
|
||||
userMemberships,
|
||||
parentDocumentUserMemberships,
|
||||
groupMemberships,
|
||||
parentDocumentGroupMemberships,
|
||||
] = await Promise.all([
|
||||
UserMembership.findRootMembershipsForDocument(document.id, undefined, {
|
||||
transaction,
|
||||
}),
|
||||
parentDocumentId
|
||||
? UserMembership.findRootMembershipsForDocument(
|
||||
parentDocumentId,
|
||||
undefined,
|
||||
{ transaction }
|
||||
)
|
||||
: [],
|
||||
GroupMembership.findRootMembershipsForDocument(document.id, undefined, {
|
||||
transaction,
|
||||
}),
|
||||
parentDocumentId
|
||||
? GroupMembership.findRootMembershipsForDocument(
|
||||
parentDocumentId,
|
||||
undefined,
|
||||
{ transaction }
|
||||
)
|
||||
: [],
|
||||
]);
|
||||
|
||||
await recalculateUserMemberships(userMemberships, transaction);
|
||||
await recalculateUserMemberships(parentDocumentUserMemberships, transaction);
|
||||
await recalculateGroupMemberships(groupMemberships, transaction);
|
||||
await recalculateGroupMemberships(
|
||||
parentDocumentGroupMemberships,
|
||||
transaction
|
||||
);
|
||||
|
||||
await Event.create(
|
||||
{
|
||||
name: "documents.move",
|
||||
@@ -288,24 +242,6 @@ async function documentMover({
|
||||
return result;
|
||||
}
|
||||
|
||||
async function recalculateUserMemberships(
|
||||
memberships: UserMembership[],
|
||||
transaction?: Transaction
|
||||
) {
|
||||
for (const membership of memberships) {
|
||||
await UserMembership.createSourcedMemberships(membership, { transaction });
|
||||
}
|
||||
}
|
||||
|
||||
async function recalculateGroupMemberships(
|
||||
memberships: GroupMembership[],
|
||||
transaction?: Transaction
|
||||
) {
|
||||
for (const membership of memberships) {
|
||||
await GroupMembership.createSourcedMemberships(membership, { transaction });
|
||||
}
|
||||
}
|
||||
|
||||
export default traceFunction({
|
||||
spanName: "documentMover",
|
||||
})(documentMover);
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
import { Transaction } from "sequelize";
|
||||
import { Document, GroupMembership, UserMembership } from "@server/models";
|
||||
import { sequelize } from "@server/storage/database";
|
||||
import { DocumentMovedEvent, Event } from "@server/types";
|
||||
import BaseProcessor from "./BaseProcessor";
|
||||
|
||||
export default class DocumentMovedProcessor extends BaseProcessor {
|
||||
static applicableEvents: Event["name"][] = ["documents.move"];
|
||||
|
||||
async perform(event: DocumentMovedEvent) {
|
||||
await sequelize.transaction(async (transaction) => {
|
||||
const document = await Document.findByPk(event.documentId, {
|
||||
transaction,
|
||||
});
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If there are any sourced memberships for this document, we need to go to the source
|
||||
// memberships and recalculate the membership for the user or group.
|
||||
const [
|
||||
userMemberships,
|
||||
parentDocumentUserMemberships,
|
||||
groupMemberships,
|
||||
parentDocumentGroupMemberships,
|
||||
] = await Promise.all([
|
||||
UserMembership.findRootMembershipsForDocument(document.id, undefined, {
|
||||
transaction,
|
||||
}),
|
||||
document.parentDocumentId
|
||||
? UserMembership.findRootMembershipsForDocument(
|
||||
document.parentDocumentId,
|
||||
undefined,
|
||||
{ transaction }
|
||||
)
|
||||
: [],
|
||||
GroupMembership.findRootMembershipsForDocument(document.id, undefined, {
|
||||
transaction,
|
||||
}),
|
||||
document.parentDocumentId
|
||||
? GroupMembership.findRootMembershipsForDocument(
|
||||
document.parentDocumentId,
|
||||
undefined,
|
||||
{ transaction }
|
||||
)
|
||||
: [],
|
||||
]);
|
||||
|
||||
await this.recalculateUserMemberships(userMemberships, transaction);
|
||||
await this.recalculateUserMemberships(
|
||||
parentDocumentUserMemberships,
|
||||
transaction
|
||||
);
|
||||
await this.recalculateGroupMemberships(groupMemberships, transaction);
|
||||
await this.recalculateGroupMemberships(
|
||||
parentDocumentGroupMemberships,
|
||||
transaction
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private async recalculateUserMemberships(
|
||||
memberships: UserMembership[],
|
||||
transaction?: Transaction
|
||||
) {
|
||||
await Promise.all(
|
||||
memberships.map((membership) =>
|
||||
UserMembership.createSourcedMemberships(membership, {
|
||||
transaction,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private async recalculateGroupMemberships(
|
||||
memberships: GroupMembership[],
|
||||
transaction?: Transaction
|
||||
) {
|
||||
await Promise.all(
|
||||
memberships.map((membership) =>
|
||||
GroupMembership.createSourcedMemberships(membership, {
|
||||
transaction,
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
+12
-9
@@ -180,6 +180,16 @@ export type UserMembershipEvent = BaseEvent<UserMembership> & {
|
||||
};
|
||||
};
|
||||
|
||||
export type DocumentMovedEvent = BaseEvent<Document> & {
|
||||
name: "documents.move";
|
||||
documentId: string;
|
||||
collectionId: string;
|
||||
data: {
|
||||
collectionIds: string[];
|
||||
documentIds: string[];
|
||||
};
|
||||
};
|
||||
|
||||
export type DocumentEvent = BaseEvent<Document> &
|
||||
(
|
||||
| {
|
||||
@@ -212,15 +222,6 @@ export type DocumentEvent = BaseEvent<Document> &
|
||||
sourceCollectionId: string;
|
||||
};
|
||||
}
|
||||
| {
|
||||
name: "documents.move";
|
||||
documentId: string;
|
||||
collectionId: string;
|
||||
data: {
|
||||
collectionIds: string[];
|
||||
documentIds: string[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
name:
|
||||
| "documents.update"
|
||||
@@ -245,6 +246,7 @@ export type DocumentEvent = BaseEvent<Document> &
|
||||
previousTitle: string;
|
||||
};
|
||||
}
|
||||
| DocumentMovedEvent
|
||||
);
|
||||
|
||||
export type EmptyTrashEvent = {
|
||||
@@ -492,6 +494,7 @@ export type Event =
|
||||
| AuthenticationProviderEvent
|
||||
| DocumentEvent
|
||||
| DocumentUserEvent
|
||||
| DocumentMovedEvent
|
||||
| DocumentGroupEvent
|
||||
| PinEvent
|
||||
| CommentEvent
|
||||
|
||||
Reference in New Issue
Block a user