技术栈
- @Cache — 根 @Module;同一插件可声明多个命名缓存
- @CacheClient(plugin, name?) — 注入本插件或其他插件的 ICache
- @CacheRoute / @DeleteCacheRoute — 按 plugin + name
- @CacheFn / @DeleteCacheFn — 按 plugin + name
- 跨插件复用 — 消费方注入所有者的缓存,不要为同一客户端再声明 @Cache
根模块上的 @Cache
@Cache 必须加在 @Module 类上——不能加在 service 或 controller。打开多个缓存时传入唯一 name。同一模块类上允许多个 @Cache。
- type — "in-memory" 或 Redis
- name — 同一插件有多个 @Cache 时需要
- 所有者是加载中的插件 — 消费方用 metadata.name(或 CacheManager.DEFAULT_PLUGIN)寻址
TSXmultiple caches in one plugin
1import { Cache, Module } from "@quan-erp/shared-backend-core";
2import metadata from "../../module.metadata.json" with { type: "json" };
3
4@Cache({
5 name: "publisher",
6 type: "in-memory",
7 checkperiod: 1000,
8})
9@Cache({
10 name: "session",
11 type: "redis",
12 host: process.env.REDIS_HOST,
13 port: Number(process.env.REDIS_PORT ?? 6379),
14 password: process.env.REDIS_PASSWORD,
15})
16@Module({
17 name: metadata.name,
18 providers: [...],
19 controllers: [...],
20})
21export class MyPluginModule {}@CacheClient
在服务属性上注入 ICache。第一个参数是拥有该缓存的插件;第二个参数是可选连接名(该插件声明了多个 @Cache 时使用)。
- CacheManager.DEFAULT_PLUGIN — 核心 / 共享默认所有者
- metadata.name — 本插件自己的缓存
- "other-plugin" — 其他插件创建的缓存
- 第二个参数 name — 命名客户端(如 "publisher")
TSXinject
1import {
2 CacheClient,
3 CacheManager,
4 Service,
5} from "@quan-erp/shared-backend-core";
6import type { ICache } from "@quan-erp/shared-backend-core";
7import metadata from "../../module.metadata.json" with { type: "json" };
8
9@Service()
10export class PublisherService {
11 // Core / default owner
12 @CacheClient(CacheManager.DEFAULT_PLUGIN, "publisher")
13 private defaultPublisher: ICache;
14
15 // This plugin’s named cache
16 @CacheClient(metadata.name, "session")
17 private session: ICache;
18
19 // Cache owned by another plugin
20 @CacheClient("warehouse", "replica")
21 private warehouseReplica: ICache;
22}使用其他插件的缓存
缓存按所有者插件(+ 可选 name)登记在进程级注册表中。消费方不要为同一客户端再声明 @Cache,而是注入所有者的缓存,并让路由/方法辅助指向相同的 plugin + name。
- 所有者 — 声明 @Cache,并先启动(写入 pluginDependencies)
- 消费方 — @CacheClient("owner-plugin", "cache-name")
- 路由 / 方法 — plugin + name 与所有者一致
- 不要在每个消费方重复声明相同的 @Cache
TSXconsumer service
1import { CacheClient, Service } from "@quan-erp/shared-backend-core";
2import type { ICache } from "@quan-erp/shared-backend-core";
3
4@Service()
5export class ReportService {
6 // "warehouse" plugin declared @Cache({ name: "replica", ... })
7 @CacheClient("warehouse", "replica")
8 private warehouseReplica: ICache;
9}路由级
- @CacheRoute({ key, plugin, name }) — key 可为字符串或 (req) => string
- @DeleteCacheRoute({ key, plugin, name }) — 回调 key 必须返回 string[]
- plugin + name 须匹配拥有该客户端的 @Cache(包括其他插件)
TSXroute cache
1import {
2 CacheRoute,
3 Controller,
4 DeleteCacheRoute,
5 Get,
6 Post,
7} from "@quan-erp/shared-backend-core";
8
9@Controller("/branch")
10export class BranchController {
11 @Get("/")
12 @CacheRoute({
13 key: (req) => `branch-${req.query.skip}-${req.query.limit}`,
14 plugin: "warehouse",
15 name: "replica",
16 })
17 async list() { /* … */ }
18
19 @Post("/")
20 @DeleteCacheRoute({
21 key: (req) => [`branch-${(req as any).user.payload.id}`],
22 plugin: "warehouse",
23 name: "replica",
24 })
25 async create() { /* … */ }
26}方法级
- @CacheFn({ key, plugin, name }) — key 为 (...args) => string
- @DeleteCacheFn({ key, plugin, name }) — key 返回 string[](允许通配符)
- 与 @CacheClient / 路由辅助相同的 plugin + name 规则
TSXmethod cache
1import {
2 CacheFn,
3 CacheManager,
4 DeleteCacheFn,
5 Service,
6} from "@quan-erp/shared-backend-core";
7import type { CreateJobDTO } from "./create-job.dto.js";
8
9@Service()
10export class JobService {
11 @CacheFn({
12 plugin: CacheManager.DEFAULT_PLUGIN,
13 name: "publisher",
14 key: (skip: number, limit: number) => `active-jobs-${skip}-${limit}`,
15 })
16 async getActiveJobs(skip: number, limit: number) { /* … */ }
17
18 @DeleteCacheFn({
19 plugin: CacheManager.DEFAULT_PLUGIN,
20 name: "publisher",
21 key: () => [`active-jobs-*`],
22 })
23 async register(dto: CreateJobDTO) { /* … */ }
24}