diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2022-12-25 09:09:46 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2022-12-25 09:09:46 +0900 |
| commit | 3e81913b6a161cfc8405bda64b4a00e8e3b1fccd (patch) | |
| tree | cf96319f405f6c7723ec7d46bbe166504ded359b /packages/backend/src/queue/processors | |
| parent | chore: fix reporisotry name (diff) | |
| download | sharkey-3e81913b6a161cfc8405bda64b4a00e8e3b1fccd.tar.gz sharkey-3e81913b6a161cfc8405bda64b4a00e8e3b1fccd.tar.bz2 sharkey-3e81913b6a161cfc8405bda64b4a00e8e3b1fccd.zip | |
feat: introduce retention-rate aggregation
Diffstat (limited to 'packages/backend/src/queue/processors')
| -rw-r--r-- | packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts new file mode 100644 index 0000000000..4650da76bb --- /dev/null +++ b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts @@ -0,0 +1,75 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { In, IsNull, MoreThan } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { Config } from '@/config.js'; +import type Logger from '@/logger.js'; +import { bindThis } from '@/decorators.js'; +import type { RetentionAggregationsRepository, UsersRepository } from '@/models/index.js'; +import { deepClone } from '@/misc/clone.js'; +import { IdService } from '@/core/IdService.js'; +import { QueueLoggerService } from '../QueueLoggerService.js'; +import type Bull from 'bull'; + +@Injectable() +export class AggregateRetentionProcessorService { + private logger: Logger; + + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + @Inject(DI.retentionAggregationsRepository) + private retentionAggregationsRepository: RetentionAggregationsRepository, + + private idService: IdService, + private queueLoggerService: QueueLoggerService, + ) { + this.logger = this.queueLoggerService.logger.createSubLogger('aggregate-retention'); + } + + @bindThis + public async process(job: Bull.Job<Record<string, unknown>>, done: () => void): Promise<void> { + this.logger.info('Aggregating retention...'); + + const now = new Date(); + const dateKey = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`; + + // 過去(だいたい)30日分のレコードを取得 + const pastRecords = await this.retentionAggregationsRepository.findBy({ + createdAt: MoreThan(new Date(Date.now() - (1000 * 60 * 60 * 24 * 31))), + }); + + // 今日登録したユーザーを全て取得 + const targetUsers = await this.usersRepository.findBy({ + host: IsNull(), + createdAt: MoreThan(new Date(Date.now() - (1000 * 60 * 60 * 24))), + }); + const targetUserIds = targetUsers.map(u => u.id); + + await this.retentionAggregationsRepository.insert({ + id: this.idService.genId(), + createdAt: now, + updatedAt: now, + userIds: targetUserIds, + usersCount: targetUserIds.length, + }); + + for (const record of pastRecords) { + const retention = record.userIds.filter(id => targetUserIds.includes(id)).length; + + const data = deepClone(record.data); + data[dateKey] = retention; + + this.retentionAggregationsRepository.update(record.id, { + updatedAt: now, + data, + }); + } + + this.logger.succ('Retention aggregated.'); + done(); + } +} |