@@ -103,6 +103,10 @@ type EngineBundle struct {
103103 // 由 EngineManager 缓存到 systemLayers,方案切换时按缓存重新注册,
104104 // 避免依赖共享 CompositeDict 的当前状态(防止与并发切换发生竞态)。
105105 SystemLayer dict.DictLayer
106+ // ExtraLayers 该方案加载的所有附加码表层(codetable-extra-<schemaID>__<dictID>)。
107+ // 由 EngineManager 缓存到 systemExtras,方案切换时按缓存清理上一个方案的 extras,
108+ // 重新注册当前方案的 extras,确保不同方案的扩展词库相互隔离。
109+ ExtraLayers []dict.DictLayer
106110}
107111
108112// SchemaResolver 方案解析器,用于混输引擎查找被引用的方案
@@ -263,15 +267,21 @@ func createCodeTableEngine(s *Schema, exeDir, dataDir string, dm *dict.DictManag
263267 }
264268
265269 // 加载附加词库(非 default 且 enabled 的词库条目)
270+ var extraLayers []dict.DictLayer
266271 if dm != nil {
267272 for _ , dictSpec := range s .Dicts {
268273 if dictSpec .Default || ! dictSpec .IsEnabled () {
269274 continue
270275 }
271276 srcPath := resolvePath (exeDir , dataDir , dictSpec .Path )
272277 cacheKey := s .Schema .ID + "_" + dictSpec .ID
273- if err := loadExtraCodetable (dm , srcPath , dictSpec , cacheKey , logger ); err != nil {
278+ layer , err := loadExtraCodetable (dm , s .Schema .ID , srcPath , dictSpec , cacheKey , logger )
279+ if err != nil {
274280 logger .Warn ("附加词库加载失败,跳过" , "dictID" , dictSpec .ID , "error" , err )
281+ continue
282+ }
283+ if layer != nil {
284+ extraLayers = append (extraLayers , layer )
275285 }
276286 }
277287 }
@@ -298,6 +308,7 @@ func createCodeTableEngine(s *Schema, exeDir, dataDir string, dm *dict.DictManag
298308 SchemaID : s .Schema .ID ,
299309 Engine : engine ,
300310 SystemLayer : ctSystemLayer ,
311+ ExtraLayers : extraLayers ,
301312 }, nil
302313}
303314
@@ -613,11 +624,19 @@ func loadCodetable(engine *codetable.Engine, srcPath string, dictType DictType,
613624 return nil
614625}
615626
616- // loadExtraCodetable 加载附加词库为独立 CodeTable,注册为 DictManager 额外 system layer。
627+ // ExtraLayerName 生成附加词库层名,使用 schemaID 前缀确保不同方案的扩展词库互相隔离。
628+ // 形式:codetable-extra-<schemaID>__<dictID>
629+ // 注意:分隔符使用 "__",避免与 schemaID/dictID 内可能出现的单下划线发生歧义。
630+ func ExtraLayerName (schemaID , dictID string ) string {
631+ return "codetable-extra-" + schemaID + "__" + dictID
632+ }
633+
634+ // loadExtraCodetable 加载附加词库为独立 CodeTable,注册为 DictManager 额外 system layer,
635+ // 并返回注册到 CompositeDict 的 layer,供调用方缓存以便方案切换时清理/重挂。
617636// 附加词库加载失败为非致命错误:调用方记录警告后跳过,不影响主词库工作。
618- func loadExtraCodetable (dm * dict.DictManager , srcPath string , spec DictSpec , cacheKey string , logger * slog.Logger ) error {
637+ func loadExtraCodetable (dm * dict.DictManager , schemaID , srcPath string , spec DictSpec , cacheKey string , logger * slog.Logger ) (dict. DictLayer , error ) {
619638 if dm == nil {
620- return nil
639+ return nil , nil
621640 }
622641
623642 srcDir := filepath .Dir (srcPath )
@@ -630,6 +649,8 @@ func loadExtraCodetable(dm *dict.DictManager, srcPath string, spec DictSpec, cac
630649
631650 logger .Info ("附加词库源文件清单" , "cacheKey" , cacheKey , "type" , spec .Type , "count" , len (srcPaths ))
632651
652+ layerName := ExtraLayerName (schemaID , spec .ID )
653+
633654 // 快捷路径:尝试加载源目录中的预编译 wdb(与 loadCodetable 行为对齐)
634655 wdbInDir := filepath .Join (srcDir , cacheKey + ".wdb" )
635656 if len (srcPaths ) > 0 && ! dictcache .NeedsRegenerate (srcPaths , wdbInDir ) {
@@ -638,11 +659,10 @@ func loadExtraCodetable(dm *dict.DictManager, srcPath string, spec DictSpec, cac
638659 } else {
639660 ct := dict .NewCodeTable ()
640661 if err := ct .LoadBinary (wdbInDir ); err == nil {
641- layerName := "codetable-extra-" + spec .ID
642662 layer := dict .NewCodeTableLayer (layerName , dict .LayerTypeSystem , ct )
643663 dm .RegisterSystemLayer (layerName , layer )
644664 logger .Info ("附加词库已注册(预编译 wdb)" , "layer" , layerName , "entryCount" , ct .EntryCount ())
645- return nil
665+ return layer , nil
646666 }
647667 }
648668 }
@@ -667,7 +687,7 @@ func loadExtraCodetable(dm *dict.DictManager, srcPath string, spec DictSpec, cac
667687 convertErr = dictcache .ConvertCodeTableToWdb (srcPath , wdbCachePath , logger )
668688 }
669689 if convertErr != nil {
670- return fmt .Errorf ("转换附加词库 %s 到 wdb 失败: %w" , cacheKey , convertErr )
690+ return nil , fmt .Errorf ("转换附加词库 %s 到 wdb 失败: %w" , cacheKey , convertErr )
671691 }
672692 }
673693
@@ -687,18 +707,17 @@ func loadExtraCodetable(dm *dict.DictManager, srcPath string, spec DictSpec, cac
687707 convertErr = dictcache .ConvertCodeTableToWdb (srcPath , wdbCachePath , logger )
688708 }
689709 if convertErr != nil {
690- return fmt .Errorf ("重新生成附加词库失败: %w" , convertErr )
710+ return nil , fmt .Errorf ("重新生成附加词库失败: %w" , convertErr )
691711 }
692712 if err := ct .LoadBinary (wdbCachePath ); err != nil {
693- return fmt .Errorf ("加载重新生成的附加词库 %s 失败: %w" , cacheKey , err )
713+ return nil , fmt .Errorf ("加载重新生成的附加词库 %s 失败: %w" , cacheKey , err )
694714 }
695715 }
696716
697- layerName := "codetable-extra-" + spec .ID
698717 layer := dict .NewCodeTableLayer (layerName , dict .LayerTypeSystem , ct )
699718 dm .RegisterSystemLayer (layerName , layer )
700719 logger .Info ("附加词库已注册" , "layer" , layerName , "entryCount" , ct .EntryCount ())
701- return nil
720+ return layer , nil
702721}
703722
704723func loadCodetableFromWdb (engine * codetable.Engine , wdbPath string ) error {
@@ -909,22 +928,31 @@ func resolvePath(exeDir, dataDir, path string) string {
909928
910929// ReloadExtraDicts 根据方案 Dicts 配置动态加载/卸载附加词库层。
911930// 用于 dict enabled 状态变更后的热重载,不重建主词库。
912- func ReloadExtraDicts (dm * dict.DictManager , s * Schema , exeDir , dataDir string , logger * slog.Logger ) {
931+ // 返回该方案当前已启用并成功加载的所有附加层,调用方负责把这份列表同步回
932+ // EngineManager.systemExtras,使得"切走 → 切回"路径仍能正确恢复 extras。
933+ func ReloadExtraDicts (dm * dict.DictManager , s * Schema , exeDir , dataDir string , logger * slog.Logger ) []dict.DictLayer {
934+ var layers []dict.DictLayer
913935 for _ , dictSpec := range s .Dicts {
914936 if dictSpec .Default {
915937 continue
916938 }
917- layerName := "codetable-extra-" + dictSpec .ID
939+ layerName := ExtraLayerName ( s . Schema . ID , dictSpec .ID )
918940 if ! dictSpec .IsEnabled () {
919941 dm .UnregisterSystemLayer (layerName )
920942 continue
921943 }
922944 srcPath := resolvePath (exeDir , dataDir , dictSpec .Path )
923945 cacheKey := s .Schema .ID + "_" + dictSpec .ID
924- if err := loadExtraCodetable (dm , srcPath , dictSpec , cacheKey , logger ); err != nil {
946+ layer , err := loadExtraCodetable (dm , s .Schema .ID , srcPath , dictSpec , cacheKey , logger )
947+ if err != nil {
925948 logger .Warn ("附加词库热重载失败" , "dictID" , dictSpec .ID , "error" , err )
949+ continue
950+ }
951+ if layer != nil {
952+ layers = append (layers , layer )
926953 }
927954 }
955+ return layers
928956}
929957
930958// createMixedEngine 创建混输引擎(五笔+拼音并行查询)
0 commit comments