| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- import { GenericCrudService } from '@d8d/shared-crud';
- import { DataSource, In } from 'typeorm';
- import { SystemConfig } from '../entities/system-config.entity';
- import { redisUtil } from '@d8d/shared-utils';
- export class SystemConfigService extends GenericCrudService<SystemConfig> {
- constructor(dataSource: DataSource) {
- super(dataSource, SystemConfig, {
- userTracking: {
- createdByField: 'createdBy',
- updatedByField: 'updatedBy'
- }
- });
- }
- /**
- * 根据配置键获取配置值(带缓存)
- */
- async getConfigByKey(configKey: string): Promise<string | null> {
- // 1. 先尝试从缓存获取
- const cachedValue = await redisUtil.getSystemConfig(configKey);
- // 2. 如果缓存命中且不是空值缓存
- if (cachedValue !== null && !redisUtil.isNullValue(cachedValue)) {
- return cachedValue;
- }
- // 3. 如果是空值缓存,直接返回null
- if (cachedValue !== null && redisUtil.isNullValue(cachedValue)) {
- return null;
- }
- // 4. 缓存未命中,查询数据库
- const config = await this.repository.findOne({
- where: { configKey }
- });
- const configValue = config?.configValue || null;
- // 5. 将结果写入缓存
- if (configValue !== null) {
- // 正常值,缓存1小时
- await redisUtil.setSystemConfig(configKey, configValue, 3600);
- } else {
- // 空值,缓存5分钟防止缓存穿透
- await redisUtil.setNullSystemConfig(configKey, 300);
- }
- return configValue;
- }
- /**
- * 根据配置键获取配置值,如果不存在则返回默认值
- */
- async getConfigByKeyWithDefault(configKey: string, defaultValue: string): Promise<string> {
- const value = await this.getConfigByKey(configKey);
- return value || defaultValue;
- }
- /**
- * 批量获取配置(带缓存)
- */
- async getConfigsByKeys(configKeys: string[]): Promise<Record<string, string>> {
- // 1. 先尝试从缓存批量获取
- const cachedValues = await redisUtil.getSystemConfigs(configKeys);
- const result: Record<string, string> = {};
- const missingKeys: string[] = [];
- // 2. 处理缓存命中的键
- configKeys.forEach(key => {
- const cachedValue = cachedValues[key];
- if (cachedValue === undefined) {
- // 空值缓存,跳过
- return;
- }
- if (cachedValue === null) {
- // 缓存未命中,需要查询数据库
- missingKeys.push(key);
- } else if (!redisUtil.isNullValue(cachedValue)) {
- // 有效缓存值
- result[key] = cachedValue;
- }
- // 如果是空值缓存(redisUtil.isNullValue返回true),不添加到结果中
- });
- // 3. 如果有未命中的键,查询数据库
- if (missingKeys.length > 0) {
- const configs = await this.repository.find({
- where: {
- configKey: In(missingKeys)
- }
- });
- const dbValues: Record<string, string> = {};
- configs.forEach(config => {
- if (config.configValue !== null) {
- dbValues[config.configKey] = config.configValue;
- }
- });
- // 4. 处理数据库查询结果并更新缓存
- const cachePromises: Promise<void>[] = [];
- missingKeys.forEach(key => {
- const dbValue = dbValues[key];
- if (dbValue !== undefined) {
- // 数据库中有值,添加到结果并缓存
- result[key] = dbValue;
- cachePromises.push(redisUtil.setSystemConfig(key, dbValue, 3600));
- } else {
- // 数据库中无值,设置空值缓存
- cachePromises.push(redisUtil.setNullSystemConfig(key, 300));
- }
- });
- // 等待所有缓存操作完成
- if (cachePromises.length > 0) {
- await Promise.all(cachePromises);
- }
- }
- return result;
- }
- /**
- * 设置配置值,如果配置键不存在则创建,存在则更新
- */
- async setConfig(configKey: string, configValue: string, description?: string): Promise<SystemConfig> {
- const existingConfig = await this.repository.findOne({
- where: { configKey }
- });
- if (existingConfig) {
- // 更新现有配置
- const updatedConfig = await this.update(existingConfig.id, {
- configValue,
- description: description || existingConfig.description
- });
- // 清除相关缓存
- await redisUtil.deleteSystemConfig(configKey);
- return updatedConfig!;
- } else {
- // 创建新配置
- const newConfig = await this.create({
- configKey,
- configValue,
- description
- } as SystemConfig);
- // 清除相关缓存(如果之前有空值缓存)
- await redisUtil.deleteSystemConfig(configKey);
- return newConfig!;
- }
- }
- /**
- * 获取所有配置
- */
- async getAllConfigs(): Promise<SystemConfig[]> {
- return await this.repository.find();
- }
- /**
- * 删除配置
- */
- async deleteConfig(configKey: string): Promise<boolean> {
- const config = await this.repository.findOne({
- where: { configKey }
- });
- if (!config) {
- return false;
- }
- await this.delete(config.id);
- // 清除相关缓存
- await redisUtil.deleteSystemConfig(configKey);
- return true;
- }
- /**
- * 重写update方法,在更新时清除缓存
- */
- override async update(id: number, data: Partial<SystemConfig>): Promise<SystemConfig | null> {
- const updatedConfig = await super.update(id, data);
- if (updatedConfig) {
- // 清除相关缓存
- await redisUtil.deleteSystemConfig(updatedConfig.configKey);
- }
- return updatedConfig;
- }
- /**
- * 重写delete方法,在删除时清除缓存
- */
- override async delete(id: number): Promise<boolean> {
- // 先获取配置信息,以便后续清除缓存
- const config = await this.getById(id);
- const result = await super.delete(id);
- if (result && config) {
- // 清除相关缓存
- await redisUtil.deleteSystemConfig(config.configKey);
- }
- return result;
- }
- /**
- * 缓存预热 - 预加载常用配置到缓存
- */
- async warmUpCache(configKeys?: string[]): Promise<void> {
- // 如果没有指定配置键,预加载所有配置
- const keysToWarm = configKeys || ['app.login.enabled', 'app.payment.enabled', 'app.notification.enabled'];
- // 批量获取配置并缓存
- await this.getConfigsByKeys(keysToWarm);
- }
- }
|