feat(server): use doc service (#9967)

close CLOUD-94
This commit is contained in:
fengmk2
2025-02-08 05:27:56 +00:00
parent ee0df52531
commit e5d1cd9ea2
17 changed files with 423 additions and 127 deletions

View File

@@ -334,7 +334,7 @@ export class PgWorkspaceDocStorageAdapter extends DocStorageAdapter {
});
if (updatedSnapshot) {
this.event.emit('doc.snapshot.updated', {
this.event.broadcast('doc.snapshot.updated', {
workspaceId: snapshot.spaceId,
docId: snapshot.docId,
});

View File

@@ -19,7 +19,11 @@ import { DocReader, DocReaderProvider } from './reader';
DocStorageCronJob,
DocReaderProvider,
],
exports: [PgWorkspaceDocStorageAdapter, PgUserspaceDocStorageAdapter],
exports: [
DocReader,
PgWorkspaceDocStorageAdapter,
PgUserspaceDocStorageAdapter,
],
})
export class DocStorageModule {}
export {

View File

@@ -1,61 +1,17 @@
import { Injectable, Logger, OnModuleInit, Optional } from '@nestjs/common';
import { Cron, CronExpression, SchedulerRegistry } from '@nestjs/schedule';
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { PrismaClient } from '@prisma/client';
import { CallMetric, Config, metrics, OnEvent } from '../../base';
import { metrics, OnEvent } from '../../base';
import { PgWorkspaceDocStorageAdapter } from './adapters/workspace';
@Injectable()
export class DocStorageCronJob implements OnModuleInit {
private busy = false;
private readonly logger = new Logger(DocStorageCronJob.name);
export class DocStorageCronJob {
constructor(
private readonly config: Config,
private readonly db: PrismaClient,
private readonly workspace: PgWorkspaceDocStorageAdapter,
@Optional() private readonly registry?: SchedulerRegistry
private readonly workspace: PgWorkspaceDocStorageAdapter
) {}
onModuleInit() {
if (this.registry && this.config.doc.manager.enableUpdateAutoMerging) {
this.registry.addInterval(
this.autoMergePendingDocUpdates.name,
// scheduler registry will clean up the interval when the app is stopped
setInterval(() => {
if (this.busy) {
return;
}
this.busy = true;
this.autoMergePendingDocUpdates()
.catch(() => {
/* never fail */
})
.finally(() => {
this.busy = false;
});
}, this.config.doc.manager.updatePollInterval)
);
this.logger.log('Updates pending queue auto merging cron started');
}
}
@CallMetric('doc', 'auto_merge_pending_doc_updates')
async autoMergePendingDocUpdates() {
try {
const randomDoc = await this.workspace.randomDoc();
if (!randomDoc) {
return;
}
await this.workspace.getDoc(randomDoc.workspaceId, randomDoc.docId);
} catch (e) {
metrics.doc.counter('auto_merge_pending_doc_updates_error').add(1);
this.logger.error('Failed to auto merge pending doc updates', e);
}
}
@Cron(CronExpression.EVERY_DAY_AT_MIDNIGHT /* everyday at 12am */)
async cleanupExpiredHistory() {
await this.db.snapshotHistory.deleteMany({