fix(server): handle hanging workspace after user account deleted (#8377)

fix CLOUD-74
This commit is contained in:
forehalo
2024-09-25 06:16:32 +00:00
parent d0050a268a
commit 1d75d97a8f
6 changed files with 43 additions and 16 deletions

View File

@@ -132,11 +132,6 @@ export class PgWorkspaceDocStorageAdapter extends DocStorageAdapter {
async deleteSpace(workspaceId: string) {
const ident = { where: { workspaceId } };
await this.db.$transaction([
this.db.workspace.deleteMany({
where: {
id: workspaceId,
},
}),
this.db.snapshot.deleteMany(ident),
this.db.update.deleteMany(ident),
this.db.snapshotHistory.deleteMany(ident),
@@ -344,6 +339,17 @@ export class PgWorkspaceDocStorageAdapter extends DocStorageAdapter {
return false;
}
const historyMaxAge = await this.options
.historyMaxAge(snapshot.spaceId)
.catch(
() =>
0 /* edgecase: user deleted but owned workspaces not handled correctly */
);
if (historyMaxAge === 0) {
return false;
}
await this.db.snapshotHistory
.create({
select: {
@@ -355,9 +361,7 @@ export class PgWorkspaceDocStorageAdapter extends DocStorageAdapter {
timestamp: new Date(snapshot.timestamp),
blob: Buffer.from(snapshot.bin),
createdBy: snapshot.editor,
expiredAt: new Date(
Date.now() + (await this.options.historyMaxAge(snapshot.spaceId))
),
expiredAt: new Date(Date.now() + historyMaxAge),
},
})
.catch(() => {

View File

@@ -2,7 +2,13 @@ import { Injectable, Logger, OnModuleInit, Optional } from '@nestjs/common';
import { Cron, CronExpression, SchedulerRegistry } from '@nestjs/schedule';
import { PrismaClient } from '@prisma/client';
import { CallTimer, Config, metrics } from '../../fundamentals';
import {
CallTimer,
Config,
type EventPayload,
metrics,
OnEvent,
} from '../../fundamentals';
import { PgWorkspaceDocStorageAdapter } from './adapters/workspace';
@Injectable()
@@ -73,4 +79,11 @@ export class DocStorageCronJob implements OnModuleInit {
.gauge('updates_queue_count')
.record(await this.db.update.count());
}
@OnEvent('user.deleted')
async clearUserWorkspaces(payload: EventPayload<'user.deleted'>) {
for (const workspace of payload.ownedWorkspaces) {
await this.workspace.deleteSpace(workspace);
}
}
}