// udeServer: 一键刷库(手动补刷) —— 按服务配置的 IP/端口/密钥/保护目录, // 调外挂程序的 /api/migrate 接口,把保护目录存量明文加密进 <目录>-cipher 并清空明文。 // 与创建流程的自动刷库(createservicelogic.notifyFuseBrush)共用 dispatchFuseBrush。 package logic import ( "context" "fmt" "udeServer/internal/svc" "udeServer/internal/types" "github.com/zeromicro/go-zero/core/logx" ) type BrushServiceLogic struct { logx.Logger ctx context.Context svcCtx *svc.ServiceContext } func NewBrushServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BrushServiceLogic { return &BrushServiceLogic{ Logger: logx.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *BrushServiceLogic) BrushService(req *types.ServiceIdReq) (*types.DeleteResp, error) { if err := checkId(req.Id); err != nil { return nil, err } svc, err := findService(l.ctx, l.svcCtx.ServiceModel, req.Id) if err != nil { return nil, err } // 挂载中拒绝刷库(第2道防线):挂载后保护目录是FUSE明文视图,历史文件已被隐藏, // 此时刷库的"清空明文"动作会穿透挂载删除底层密文,数据全失。 // 前端按钮点击时已有同款拦截(第1道防线),后端这道防的是绕过前端直接调接口; // 外挂侧 rejectIfMounted 查挂载注册表兜底(第3道防线,防库状态过时)。 if svc.MountStatus.String == "mounted" { return nil, fmt.Errorf("历史文件已被挂载隐藏,请先卸掉挂载再执行刷库操作") } // 查该服务的全部保护目录(目录表按 service_id 过滤) dirs, err := l.svcCtx.DirectoryModel.FindDirsByServiceId(l.ctx, req.Id) if err != nil { return nil, fmt.Errorf("查询保护目录失败: %w", err) } if len(dirs) == 0 { return nil, fmt.Errorf("该服务未配置保护目录,无库可刷") } // 下发刷库:手动补刷是显式操作,失败直接返回错误,前端红色提示(与创建流程的软处理不同) if err := dispatchFuseBrush(l.ctx, l.svcCtx, svc, dirs); err != nil { l.Errorf("brush dispatch failed, service id: %d, err: %v", req.Id, err) return nil, err } l.Infof("brush dispatch ok, service id: %d, dirs: %v", req.Id, dirs) return &types.DeleteResp{Ok: true}, nil }