Skip to content
This repository has been archived by the owner on Oct 10, 2024. It is now read-only.

Commit

Permalink
给个清理命令
Browse files Browse the repository at this point in the history
  • Loading branch information
bangbang93 committed Nov 10, 2021
1 parent 93ac403 commit 929466e
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 17 deletions.
2 changes: 2 additions & 0 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {ConfigModule, ConfigService} from '@nestjs/config'
import {BunyanLoggerModule} from 'nestjs-bunyan'
import {join} from 'path'
import {cwd} from 'process'
import {CleanModule} from './clean/clean.module'
import {ConvertModule} from './convert/convert.module'

@Module({
Expand Down Expand Up @@ -30,6 +31,7 @@ import {ConvertModule} from './convert/convert.module'
}),

ConvertModule,
CleanModule,
],
})
export class AppModule {}
46 changes: 46 additions & 0 deletions src/app/clean/clean.command.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import * as Logger from 'bunyan'
import {difference, isEqual, uniq} from 'lodash'
import {Command, CommandRunner, InquirerService} from 'nest-commander'
import {InjectLogger} from 'nestjs-bunyan'
import {CleanService} from './clean.service'

@Command({
name: 'clean',
arguments: '[tasks...]',
})
export class CleanCommand implements CommandRunner {
@InjectLogger() private readonly logger: Logger
private readonly tasks = {
user: '用户',
userWallet: '用户钱包',
category: '分类',
thread: '主题',
post: '回复',
attachment: '附件',
emoji: '表情',
}

constructor(
private readonly inquirerService: InquirerService,
private readonly cleanService: CleanService,
) {}

public async run(tasks: string[]): Promise<void> {
tasks = uniq(tasks)
let parts = Object.keys(this.tasks)
if (tasks.length && !isEqual(tasks, ['all'])) {
const left = difference(tasks, parts)
if (left.length !== 0) throw new Error(`未知清理类型 ${left}`)
parts = parts.filter((e) => tasks.includes(e))
}
const taskNames = parts.map((e) => this.tasks[e])
const confirm = await this.inquirerService.ask('confirm', {taskNames, tasks, confirm: undefined})
if (!confirm.confirm) return
this.logger.info('run task %s', parts)
for (const part of parts) {
this.logger.info(`开始清理${this.tasks[part]},请稍候`)
const count = await this.cleanService[part]()
this.logger.info(`删除${count}条数据`)
}
}
}
15 changes: 15 additions & 0 deletions src/app/clean/clean.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {Module} from '@nestjs/common'
import {ModelsModule} from '../models/models.module'
import {CleanCommand} from './clean.command'
import {ConfirmQuestion} from './confirm.question'

@Module({
imports: [
ModelsModule,
],
providers: [
CleanCommand,
ConfirmQuestion,
],
})
export class CleanModule {}
64 changes: 64 additions & 0 deletions src/app/clean/clean.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {Injectable} from '@nestjs/common'
import {AttachmentModel} from '../models/q/attachment.model'
import {CategoryModel} from '../models/q/category.model'
import {EmojiModel} from '../models/q/emoji.model'
import {GroupPermissionModel} from '../models/q/group-permission.model'
import {PostModel} from '../models/q/post.model'
import {ThreadModel} from '../models/q/thread.model'
import {UserWalletModel} from '../models/q/user-wallet.model'
import {UserModel} from '../models/q/user.model'
import {ForumImagetypeModel} from '../models/x/forum-imagetype.model'

@Injectable()
export class CleanService {
constructor(
private readonly userModel: UserModel,
private readonly userWalletModel: UserWalletModel,
private readonly categoryModel: CategoryModel,
private readonly groupPermissionModel: GroupPermissionModel,
private readonly postModel: PostModel,
private readonly threadModel: ThreadModel,
private readonly attachmentModel: AttachmentModel,
private readonly forumImagetypeModel: ForumImagetypeModel,
private readonly emojiModel: EmojiModel,
) {}

public async user(): Promise<number> {
return this.userModel.query.where('id', '>', 1).delete()
}

public async userWallet(): Promise<number> {
return this.userWalletModel.query.where('user_id', '>', 1).delete()
}

public async category(): Promise<number> {
const categories = await this.categoryModel.query.where('id', '>', 1).select()
for (const category of categories) {
const permissions = this.groupPermissionModel.getCategoryPermissions(category)
for (const permission of permissions) {
await this.groupPermissionModel.query.where('group_id', permission.group_id)
.andWhere('permission', permission.permission)
.delete()
}
}
return this.categoryModel.query.where('id', '>', 1).delete()
}

public async thread(): Promise<number> {
await this.postModel.query.where('is_first', 1).delete()
return this.threadModel.query.where('id', '>', 0).delete()
}

public async post(): Promise<number> {
return this.postModel.query.where('is_first', 0).delete()
}

public async attachment(): Promise<number> {
return this.attachmentModel.query.where('id', '>', 0).delete()
}

public async emoji(): Promise<number> {
const imageTypes = await this.forumImagetypeModel.query.select()
return this.emojiModel.query.whereIn('category', imageTypes.map((e) => e.directory))
}
}
18 changes: 18 additions & 0 deletions src/app/clean/confirm.question.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {MessageFor, Question, QuestionSet} from 'nest-commander'

@QuestionSet({name: 'confirm'})
export class ConfirmQuestion {
@Question({
name: 'confirm',
})
public confirm(val: string): boolean {
return val === 'yes i do'
}

@MessageFor({name: 'confirm'})
public confirmMessage({taskNames}: {taskNames: string[]}): string {
return `请确认要清理所有转换相关的数据?将清理${taskNames.join('、')}转换数据
如确认,请输入 'yes i do'
`
}
}
34 changes: 18 additions & 16 deletions src/app/convert/base.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,17 @@ export abstract class BaseService implements OnModuleInit {
protected batchSize: number
protected concurrent: number = 50
protected dryRun = false
protected maxThreads = cpus().length

public onModuleInit(): void {
this.highWaterMark = this.configService.get('HighWaterMark')
this.batchSize = parseInt(this.configService.get('BATCH_SIZE', '1000'), 10)
let maxThreads = parseInt(this.configService.get('MAX_THREAD', '0'), 10)
if (isNaN(maxThreads) || maxThreads === 0) {
maxThreads = cpus().length
this.maxThreads = parseInt(this.configService.get('MAX_THREAD', '0'), 10)
if (isNaN(this.maxThreads) || this.maxThreads === 0) {
this.maxThreads = cpus().length
}
this.concurrent = maxThreads * 20
this.concurrent = this.maxThreads * 20
this.dryRun = toBoolean(this.configService.get('DRY_RUN', 'false'))

if (!piscina) {
piscina = new Piscina({
filename: require.resolve('../../worker'),
idleTimeout: ms('1h'),
maxThreads,
workerData: {
mode: this.configService.get('CONVERT_MODE', 'html'),
},
})
}
}

public getBar(name: string, total: number): ProgressBar {
Expand All @@ -55,7 +45,19 @@ export abstract class BaseService implements OnModuleInit {
}

protected get piscina(): Piscina {
return piscina
if (piscina) {
return piscina
} else {
piscina = new Piscina({
filename: require.resolve('../../worker'),
idleTimeout: ms('1h'),
maxThreads: this.maxThreads,
workerData: {
mode: this.configService.get('CONVERT_MODE', 'html'),
},
})
return piscina
}
}

public abstract execute(): Promise<void>
Expand Down
2 changes: 1 addition & 1 deletion src/app/convert/convert.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {UserService} from './converter/user.service'
@Command({
name: 'convert',
description: '转换',
arguments: '<tasks...>',
arguments: '[tasks...]',
})
export class ConvertService implements CommandRunner {
@InjectLogger() private readonly logger: Logger
Expand Down

0 comments on commit 929466e

Please sign in to comment.