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

@@ -1,67 +1,39 @@
import { mock } from 'node:test';
import { ScheduleModule } from '@nestjs/schedule';
import { TestingModule } from '@nestjs/testing';
import { PrismaClient } from '@prisma/client';
import test from 'ava';
import * as Sinon from 'sinon';
import ava, { TestFn } from 'ava';
import { Config } from '../../base/config';
import { DocStorageModule } from '../../core/doc';
import { DocStorageCronJob } from '../../core/doc/job';
import { createTestingModule } from '../utils';
import { createTestingModule, type TestingModule } from '../utils';
let m: TestingModule;
let timer: Sinon.SinonFakeTimers;
let db: PrismaClient;
interface Context {
module: TestingModule;
db: PrismaClient;
cronJob: DocStorageCronJob;
}
const test = ava as TestFn<Context>;
// cleanup database before each test
test.before(async () => {
timer = Sinon.useFakeTimers({
toFake: ['setInterval'],
});
m = await createTestingModule({
test.before(async t => {
t.context.module = await createTestingModule({
imports: [ScheduleModule.forRoot(), DocStorageModule],
});
db = m.get(PrismaClient);
t.context.db = t.context.module.get(PrismaClient);
t.context.cronJob = t.context.module.get(DocStorageCronJob);
});
test.after.always(async () => {
await m.close();
timer.restore();
test.beforeEach(async t => {
await t.context.module.initTestingDB();
});
test('should poll when intervel due', async t => {
const manager = m.get(DocStorageCronJob);
const interval = m.get(Config).doc.manager.updatePollInterval;
let resolve: any;
const fake = mock.method(manager, 'autoMergePendingDocUpdates', () => {
return new Promise(_resolve => {
resolve = _resolve;
});
});
timer.tick(interval);
t.is(fake.mock.callCount(), 1);
// busy
timer.tick(interval);
// @ts-expect-error private member
t.is(manager.busy, true);
t.is(fake.mock.callCount(), 1);
resolve();
await timer.tickAsync(1);
// @ts-expect-error private member
t.is(manager.busy, false);
timer.tick(interval);
t.is(fake.mock.callCount(), 2);
test.after.always(async t => {
await t.context.module.close();
});
test('should be able to cleanup expired history', async t => {
const { db } = t.context;
const timestamp = Date.now();
// insert expired data
@@ -93,7 +65,7 @@ test('should be able to cleanup expired history', async t => {
let count = await db.snapshotHistory.count();
t.is(count, 20);
await m.get(DocStorageCronJob).cleanupExpiredHistory();
await t.context.cronJob.cleanupExpiredHistory();
count = await db.snapshotHistory.count();
t.is(count, 10);

View File

@@ -1,8 +1,4 @@
import {
ConsoleLogger,
INestApplication,
ModuleMetadata,
} from '@nestjs/common';
import { INestApplication, LogLevel, ModuleMetadata } from '@nestjs/common';
import { APP_GUARD, ModuleRef } from '@nestjs/core';
import { Query, Resolver } from '@nestjs/graphql';
import {
@@ -17,12 +13,15 @@ import type { Response } from 'supertest';
import supertest from 'supertest';
import { AppModule, FunctionalityModules } from '../../app.module';
import { GlobalExceptionFilter, Runtime } from '../../base';
import { AFFiNELogger, GlobalExceptionFilter, Runtime } from '../../base';
import { GqlModule } from '../../base/graphql';
import { AuthGuard, AuthModule } from '../../core/auth';
import { RefreshFeatures0001 } from '../../data/migrations/0001-refresh-features';
import { ModelsModule } from '../../models';
const TEST_LOG_LEVEL: LogLevel =
(process.env.TEST_LOG_LEVEL as LogLevel) ?? 'fatal';
async function flushDB(client: PrismaClient) {
const result: { tablename: string }[] =
await client.$queryRaw`SELECT tablename
@@ -39,7 +38,7 @@ async function flushDB(client: PrismaClient) {
);
}
interface TestingModuleMeatdata extends ModuleMetadata {
interface TestingModuleMetadata extends ModuleMetadata {
tapModule?(m: TestingModuleBuilder): void;
tapApp?(app: INestApplication): void;
}
@@ -85,7 +84,7 @@ class MockResolver {
}
export async function createTestingModule(
moduleDef: TestingModuleMeatdata = {},
moduleDef: TestingModuleMetadata = {},
autoInitialize = true
): Promise<TestingModule> {
// setting up
@@ -127,7 +126,7 @@ export async function createTestingModule(
// can't tolerate the noisy logs
// @ts-expect-error private
m.applyLogger({
logger: ['fatal'],
logger: [TEST_LOG_LEVEL],
});
const runtime = m.get(Runtime);
// by pass password min length validation
@@ -146,7 +145,7 @@ export async function createTestingModule(
}
export async function createTestingApp(
moduleDef: TestingModuleMeatdata = {}
moduleDef: TestingModuleMetadata = {}
): Promise<{ module: TestingModule; app: TestingApp }> {
const m = await createTestingModule(moduleDef, false);
@@ -155,9 +154,9 @@ export async function createTestingApp(
bodyParser: true,
rawBody: true,
}) as TestingApp;
const logger = new ConsoleLogger();
const logger = new AFFiNELogger();
logger.setLogLevels(['fatal']);
logger.setLogLevels([TEST_LOG_LEVEL]);
app.useLogger(logger);
app.useGlobalFilters(new GlobalExceptionFilter(app.getHttpAdapter()));