fix(server): avoid repeatly register providers (#5265)

This commit is contained in:
liuyi
2023-12-13 02:12:37 +00:00
parent f4a52c031f
commit 797cd5c6eb
12 changed files with 34 additions and 53 deletions

View File

@@ -16,6 +16,8 @@ export enum ExternalAccount {
firebase = 'firebase', firebase = 'firebase',
} }
export type ServerFlavor = 'allinone' | 'graphql' | 'sync' | 'selfhosted';
type EnvConfigType = 'string' | 'int' | 'float' | 'boolean'; type EnvConfigType = 'string' | 'int' | 'float' | 'boolean';
type ConfigPaths = LeafPaths< type ConfigPaths = LeafPaths<
Omit< Omit<
@@ -345,6 +347,11 @@ export interface AFFiNEConfig {
doc: { doc: {
manager: { manager: {
/**
* Whether auto merge updates into doc snapshot.
*/
enableUpdateAutoMerging: boolean;
/** /**
* How often the [DocManager] will start a new turn of merging pending updates into doc snapshot. * How often the [DocManager] will start a new turn of merging pending updates into doc snapshot.
* *

View File

@@ -7,9 +7,12 @@ import { join } from 'node:path';
import parse from 'parse-duration'; import parse from 'parse-duration';
import pkg from '../../package.json' assert { type: 'json' }; import pkg from '../../package.json' assert { type: 'json' };
import type { AFFiNEConfig } from './def'; import type { AFFiNEConfig, ServerFlavor } from './def';
import { applyEnvToConfig } from './env'; import { applyEnvToConfig } from './env';
export const SERVER_FLAVOR = (process.env.SERVER_FLAVOR ??
'allinone') as ServerFlavor;
// Don't use this in production // Don't use this in production
export const examplePrivateKey = `-----BEGIN EC PRIVATE KEY----- export const examplePrivateKey = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEtyAJLIULkphVhqXqxk4Nr8Ggty3XLwUJWBxzAWCWTMoAoGCCqGSM49 MHcCAQEEIEtyAJLIULkphVhqXqxk4Nr8Ggty3XLwUJWBxzAWCWTMoAoGCCqGSM49
@@ -206,6 +209,7 @@ export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
}, },
doc: { doc: {
manager: { manager: {
enableUpdateAutoMerging: SERVER_FLAVOR !== 'sync',
updatePollInterval: 3000, updatePollInterval: 3000,
experimentalMergeWithJwstCodec: false, experimentalMergeWithJwstCodec: false,
}, },

View File

@@ -73,3 +73,4 @@ export class ConfigModule {
} }
export type { AFFiNEConfig } from './def'; export type { AFFiNEConfig } from './def';
export { SERVER_FLAVOR } from './default';

View File

@@ -28,12 +28,10 @@ export class EventEmitter {
} }
} }
export const OnEvent = ( export const OnEvent = RawOnEvent as (
event: Event, event: Event,
opts?: Parameters<typeof RawOnEvent>[1] opts?: Parameters<typeof RawOnEvent>[1]
) => { ) => MethodDecorator;
return RawOnEvent(event, opts);
};
@Global() @Global()
@Module({ @Module({

View File

@@ -1,7 +1,7 @@
import { Module } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { Field, ObjectType, Query } from '@nestjs/graphql'; import { Field, ObjectType, Query } from '@nestjs/graphql';
export const { SERVER_FLAVOR } = process.env; import { SERVER_FLAVOR } from '../config';
@ObjectType() @ObjectType()
export class ServerConfigType { export class ServerConfigType {
@@ -19,7 +19,7 @@ export class ServerConfigResolver {
serverConfig(): ServerConfigType { serverConfig(): ServerConfigType {
return { return {
version: AFFiNE.version, version: AFFiNE.version,
flavor: SERVER_FLAVOR || 'allinone', flavor: SERVER_FLAVOR,
}; };
} }
} }

View File

@@ -1,38 +1,12 @@
import { DynamicModule } from '@nestjs/common'; import { Module } from '@nestjs/common';
import { DocHistoryManager } from './history'; import { DocHistoryManager } from './history';
import { DocManager } from './manager'; import { DocManager } from './manager';
export class DocModule { @Module({
/** providers: [DocManager, DocHistoryManager],
* @param automation whether enable update merging automation logic exports: [DocManager, DocHistoryManager],
*/ })
private static defModule(automation = true): DynamicModule { export class DocModule {}
return {
module: DocModule,
providers: [
{
provide: 'DOC_MANAGER_AUTOMATION',
useValue: automation,
},
DocManager,
DocHistoryManager,
],
exports: [DocManager, DocHistoryManager],
};
}
static forRoot() {
return this.defModule();
}
static forSync(): DynamicModule {
return this.defModule(false);
}
static forFeature(): DynamicModule {
return this.defModule(false);
}
}
export { DocHistoryManager, DocManager }; export { DocHistoryManager, DocManager };

View File

@@ -1,5 +1,4 @@
import { import {
Inject,
Injectable, Injectable,
Logger, Logger,
OnModuleDestroy, OnModuleDestroy,
@@ -97,8 +96,6 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
private busy = false; private busy = false;
constructor( constructor(
@Inject('DOC_MANAGER_AUTOMATION')
private readonly automation: boolean,
private readonly db: PrismaService, private readonly db: PrismaService,
private readonly config: Config, private readonly config: Config,
private readonly cache: Cache, private readonly cache: Cache,
@@ -106,7 +103,7 @@ export class DocManager implements OnModuleInit, OnModuleDestroy {
) {} ) {}
onModuleInit() { onModuleInit() {
if (this.automation) { if (this.config.doc.manager.enableUpdateAutoMerging) {
this.logger.log('Use Database'); this.logger.log('Use Database');
this.setup(); this.setup();
} }

View File

@@ -1,8 +1,9 @@
import { DynamicModule, Type } from '@nestjs/common'; import { DynamicModule, Type } from '@nestjs/common';
import { ScheduleModule } from '@nestjs/schedule'; import { ScheduleModule } from '@nestjs/schedule';
import { SERVER_FLAVOR } from '../config';
import { GqlModule } from '../graphql.module'; import { GqlModule } from '../graphql.module';
import { SERVER_FLAVOR, ServerConfigModule } from './config'; import { ServerConfigModule } from './config';
import { DocModule } from './doc'; import { DocModule } from './doc';
import { PaymentModule } from './payment'; import { PaymentModule } from './payment';
import { SelfHostedModule } from './self-hosted'; import { SelfHostedModule } from './self-hosted';
@@ -14,7 +15,7 @@ const BusinessModules: (Type | DynamicModule)[] = [];
switch (SERVER_FLAVOR) { switch (SERVER_FLAVOR) {
case 'sync': case 'sync':
BusinessModules.push(SyncModule, DocModule.forSync()); BusinessModules.push(SyncModule, DocModule);
break; break;
case 'selfhosted': case 'selfhosted':
BusinessModules.push( BusinessModules.push(
@@ -25,7 +26,7 @@ switch (SERVER_FLAVOR) {
WorkspaceModule, WorkspaceModule,
UsersModule, UsersModule,
SyncModule, SyncModule,
DocModule.forRoot() DocModule
); );
break; break;
case 'graphql': case 'graphql':
@@ -35,7 +36,7 @@ switch (SERVER_FLAVOR) {
GqlModule, GqlModule,
WorkspaceModule, WorkspaceModule,
UsersModule, UsersModule,
DocModule.forRoot(), DocModule,
PaymentModule PaymentModule
); );
break; break;
@@ -48,7 +49,7 @@ switch (SERVER_FLAVOR) {
WorkspaceModule, WorkspaceModule,
UsersModule, UsersModule,
SyncModule, SyncModule,
DocModule.forRoot(), DocModule,
PaymentModule PaymentModule
); );
break; break;

View File

@@ -5,7 +5,7 @@ import { PermissionService } from '../../workspaces/permission';
import { EventsGateway } from './events.gateway'; import { EventsGateway } from './events.gateway';
@Module({ @Module({
imports: [DocModule.forFeature()], imports: [DocModule],
providers: [EventsGateway, PermissionService], providers: [EventsGateway, PermissionService],
}) })
export class EventsModule {} export class EventsModule {}

View File

@@ -8,7 +8,7 @@ import { PermissionService } from './permission';
import { PagePermissionResolver, WorkspaceResolver } from './resolver'; import { PagePermissionResolver, WorkspaceResolver } from './resolver';
@Module({ @Module({
imports: [DocModule.forFeature()], imports: [DocModule],
controllers: [WorkspacesController], controllers: [WorkspacesController],
providers: [ providers: [
WorkspaceResolver, WorkspaceResolver,

View File

@@ -9,14 +9,13 @@ import {
import Redis from 'ioredis'; import Redis from 'ioredis';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis'; import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
import { Config, ConfigModule } from './config'; import { Config } from './config';
import { getRequestResponseFromContext } from './utils/nestjs'; import { getRequestResponseFromContext } from './utils/nestjs';
@Global() @Global()
@Module({ @Module({
imports: [ imports: [
ThrottlerModule.forRootAsync({ ThrottlerModule.forRootAsync({
imports: [ConfigModule],
inject: [Config], inject: [Config],
useFactory: (config: Config): ThrottlerModuleOptions => { useFactory: (config: Config): ThrottlerModuleOptions => {
const options: ThrottlerModuleOptions = { const options: ThrottlerModuleOptions = {

View File

@@ -26,7 +26,7 @@ const createModule = () => {
CacheModule, CacheModule,
EventModule, EventModule,
ConfigModule.forRoot(), ConfigModule.forRoot(),
DocModule.forRoot(), DocModule,
], ],
}).compile(); }).compile();
}; };