Skip to content

Commit

Permalink
refactor(core): migrate aggregate injecting private service to use Cl…
Browse files Browse the repository at this point in the history
…ientModule (#850)
  • Loading branch information
wibus-wee authored Sep 2, 2023
1 parent f3d45d2 commit 4c1e503
Show file tree
Hide file tree
Showing 7 changed files with 179 additions and 110 deletions.
20 changes: 15 additions & 5 deletions apps/core/src/modules/aggregate/aggregate.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Coding With IU
*/

import { Controller, Get, Query } from '@nestjs/common';
import { Controller, Get, Inject, Query } from '@nestjs/common';
import { CacheKey, CacheTTL } from '@nestjs/cache-manager';
import { ApiOperation } from '@nestjs/swagger';
import { Auth } from '~/shared/common/decorator/auth.decorator';
Expand All @@ -16,12 +16,18 @@ import { IsMaster } from '~/shared/common/decorator/role.decorator';
import { CacheKeys } from '~/shared/constants/cache.constant';
import { TopQueryDto } from './aggregate.dto';
import { AggregateService } from './aggregate.service';
import { ServicesEnum } from '~/shared/constants/services.constant';
import { ClientProxy } from '@nestjs/microservices';
import { transportReqToMicroservice } from '~/shared/microservice.transporter';
import { ConfigEvents } from '~/shared/constants/event.constant';

@Controller('aggregate')
@ApiName
export class AggregateController {
constructor(
private readonly aggregateService: AggregateService,
@Inject(ServicesEnum.config)
private readonly configService: ClientProxy,
) {}

@Get('/')
Expand All @@ -33,10 +39,13 @@ export class AggregateController {
// this.configService.getMaster(),
this.aggregateService.getAllCategory(),
this.aggregateService.getAllPages(),
// this.configService.get("urls"),
// this.configService.get("site"),
transportReqToMicroservice(
this.configService,
ConfigEvents.ConfigGetByMaster,
'site',
),
]);
const [categories, pageMeta] = tasks.map((t) => {
const [categories, pageMeta, site] = tasks.map((t) => {
if (t.status === 'fulfilled') {
return t.value;
} else {
Expand All @@ -46,6 +55,7 @@ export class AggregateController {
return {
categories,
pageMeta,
site,
};
}

Expand Down Expand Up @@ -74,7 +84,7 @@ export class AggregateController {

@Get('/stat')
@ApiOperation({ summary: '获取网站统计信息' })
@Auth()
// @Auth()
async stat() {
const [count] = await Promise.all([this.aggregateService.getCounts()]);
return {
Expand Down
4 changes: 4 additions & 0 deletions apps/core/src/modules/aggregate/aggregate.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import { REDIS_TRANSPORTER } from '~/shared/constants/transporter.constants';
name: ServicesEnum.config,
...REDIS_TRANSPORTER,
},
{
name: ServicesEnum.page,
...REDIS_TRANSPORTER,
}
]),
],
controllers: [AggregateController],
Expand Down
198 changes: 97 additions & 101 deletions apps/core/src/modules/aggregate/aggregate.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,66 +7,47 @@
* Coding With IU
*/

import { forwardRef, Inject, Injectable } from '@nestjs/common';
import { ReturnModelType } from '@typegoose/typegoose';
import { AnyParamConstructor } from '@typegoose/typegoose/lib/types';
import { pick } from 'lodash';
import { CategoryService } from '~/apps/page-service/src/category.service';
import { Inject, Injectable } from '@nestjs/common';
import { CategoryModel } from '~/apps/page-service/src/model/category.model';
import { PageService } from '~/apps/page-service/src/page-service.service';
import { PostService } from '~/apps/page-service/src/post-service.service';
import { CacheService } from '~/libs/cache/src';
import { CacheKeys } from '~/shared/constants/cache.constant';
import { RSSProps } from './aggregate.interface';
import { ServicesEnum } from '~/shared/constants/services.constant';
import { ClientProxy } from '@nestjs/microservices';
import { ConfigEvents } from '~/shared/constants/event.constant';
import {
CategoryEvents,
ConfigEvents,
PageEvents,
PostEvents,
} from '~/shared/constants/event.constant';
import { transportReqToMicroservice } from '~/shared/microservice.transporter';
import { PostModel } from '~/apps/page-service/src/model/post.model';

@Injectable()
export class AggregateService {
constructor(
@Inject(forwardRef(() => PostService))
private readonly postService: PostService,
@Inject(forwardRef(() => PageService))
private readonly pageService: PageService,
@Inject(forwardRef(() => CategoryService))
private readonly categoryService: CategoryService,
@Inject(ServicesEnum.page)
private readonly pageService: ClientProxy,
@Inject(ServicesEnum.config)
private readonly configService: ClientProxy,
private readonly redis: CacheService,
) {}

getAllCategory() {
return this.categoryService.getAllCategories();
async getAllCategory() {
// return this.categoryService.getAllCategories();
return await transportReqToMicroservice(
this.pageService,
CategoryEvents.CategoryGetAll,
{},
);
}

getAllPages() {
return this.pageService.model
.find({}, 'title _id slug order')
.sort({
order: -1,
modified: -1,
})
.lean();
}

/**
* findTop 查询最新文章
* @param model 模型
* @param condition 查询条件
* @param size 获取数量
*/
private findTop<
U extends AnyParamConstructor<any>,
T extends ReturnModelType<U>,
>(model: T, condition = {}, size = 6) {
// 获取置顶文章
return model
.find(condition)
.sort({ created: -1 })
.limit(size)
.select('_id title name slug created text');
async getAllPages() {
return await transportReqToMicroservice(
this.pageService,
PageEvents.PagesGetAll,
{},
);
}

/**
Expand All @@ -75,24 +56,15 @@ export class AggregateService {
* @param isMaster 是否主人
*/
async topActivity(size = 6, isMaster = false) {
const [posts] = await Promise.all([
this.findTop(
this.postService.model,
!isMaster ? { hide: false } : {},
const posts = await transportReqToMicroservice<PostModel[]>(
this.pageService,
PostEvents.PostGetTopActivity,
{
size,
)
.populate('categoryId')
.lean()
.then((res) => {
return res.map((post) => {
post.category = pick(post.categoryId, ['name', 'slug']);
delete post.categoryId;
return post;
});
}),
]);

return { posts };
isMaster,
},
);
return posts;
}

/**
Expand All @@ -102,14 +74,21 @@ export class AggregateService {
// const {
// urls: { webUrl: baseURL },
// } = await this.configService.waitForConfigReady();
const { frontUrl: baseURL } = await transportReqToMicroservice(
this.configService,
ConfigEvents.ConfigGetByMaster,
'site',
);
const combineTasks = await Promise.all([
this.postService.model
.find({
hide: false, // 只获取发布的文章
password: { $nq: null }, // 只获取没有密码的文章
rss: true, // 只获取公开RSS的文章
})
.populate('category')
transportReqToMicroservice<PostModel[]>( // FIX: Maybe here will be crash.
this.pageService,
PostEvents.PostsListGetAll,
{
hide: false,
password: false,
rss: true,
},
)
.then((list) => {
// 如果文章存在密码,则不获取
return list.filter((document) => {
Expand All @@ -123,7 +102,7 @@ export class AggregateService {
`/posts/${(document.category as CategoryModel).slug}/${
document.slug
}`,
// baseURL
baseURL,
),
published_at: document.modified
? new Date(document.modified)
Expand All @@ -141,41 +120,50 @@ export class AggregateService {
* getRSSFeedContent 获取RSS内容
*/
async getRSSFeedContent() {
// const {
// urls: { webUrl },
// } = await this.configService.waitForConfigReady();

// const baseURL = webUrl.replace(/\/$/, "");
const { frontUrl: baseURL } = await transportReqToMicroservice(
this.configService,
ConfigEvents.ConfigGetByMaster,
'site',
);

const [posts] = await Promise.all([
await this.postService.model
.find({
transportReqToMicroservice<PostModel[]>( // FIX: Maybe here will be crash.
this.pageService,
PostEvents.PostsListGetAll,
{
hide: false,
password: false,
rss: true,
})
.limit(10)
.sort({ created: -1 })
.populate('category')
.then((list) => {
// 如果文章存在密码,则不获取
return list.filter((document) => {
return document.password === null;
});
}),
},
).then((list) => {
return list.filter((document) => {
return document.password === null;
});
}),
]);
const postsRss: RSSProps['data'] = posts.map((post) => {
return {
id: String(post._id),
id: String(post.id),
title: post.title,
text: post.text,
created: post.created!,
modified: post.modified || null,
// link: baseURL + this.urlService.build(post),
link: new URL(
`/posts/${(post.category as CategoryModel).slug}/${post.slug}`,
baseURL,
),
};
});
return postsRss
.sort((a, b) => b.created!.getTime() - a.created!.getTime())
.slice(0, 10);
return (
postsRss
// created 传输过来会自动从 Date 转换为 String,所以需要重新转换
.sort(
(a, b) =>
new Date(b.created as any).getTime() -
new Date(a.created as any).getTime(),
)
.slice(0, 10)
);
}

/**
Expand All @@ -184,26 +172,34 @@ export class AggregateService {
*/
async buildRssStructure(): Promise<RSSProps> {
const data = await this.getRSSFeedContent();
const title = (await transportReqToMicroservice(
this.configService,
ConfigEvents.ConfigGetByMaster,
'seo',
)).title || '';
const title =
(
await transportReqToMicroservice(
this.configService,
ConfigEvents.ConfigGetByMaster,
'seo',
)
).title || '';
return {
title,
data,
};
}

async getCounts() {
async function countDocuments(
client: ClientProxy,
event: string,
options?: any,
): Promise<number> {
const list = await transportReqToMicroservice(client, event, options || {});
return list.length;
}

const [posts, pages, categories] = await Promise.all([
this.postService.model.countDocuments({
hide: false,
password: { $nq: null },
rss: true,
}),
this.pageService.model.countDocuments(),
this.categoryService.model.countDocuments(),
countDocuments(this.pageService, PostEvents.PostsListGetAll),
countDocuments(this.pageService, PageEvents.PagesGetAll),
countDocuments(this.pageService, CategoryEvents.CategoryGetAll),
]);

return {
Expand Down
17 changes: 15 additions & 2 deletions apps/page-service/src/page-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,15 @@ export class PageServiceController {
}

@MessagePattern({ cmd: PostEvents.PostsListGetAll })
async getPostsList() {
return this.postService.model.find().sort({ created: -1 });
async getPostsList(condition?: {
hide?: boolean;
password?: boolean;
rss?: boolean;
}) {
return this.postService.model.find({
...condition,
password: condition?.password ? { $ne: null } : null,
}).sort({ created: -1 });
}

@MessagePattern({ cmd: PostEvents.PostGetByMaster })
Expand Down Expand Up @@ -275,4 +282,10 @@ export class PageServiceController {
async thumbUpPost(_id: string) {
throw new NotImplementedRpcExcption('Not Implemented');
}

@MessagePattern({ cmd: PostEvents.PostGetTopActivity })
@ApiOperation({ summary: '获取热门文章' })
async getTopActivity(input: { size: number; isMaster: boolean }) {
return this.postService.topActivity(input.size, input.isMaster);
}
}
Loading

0 comments on commit 4c1e503

Please sign in to comment.