alist icon indicating copy to clipboard operation
alist copied to clipboard

多服务器共用数据库时,新增或删除存储,文件列表刷新失效

Open ForSourceCodeAnalysis opened this issue 7 months ago • 1 comments

Please make sure of the following things

  • [X] I have read the documentation. 我已经阅读了文档

  • [X] I'm sure there are no duplicate issues or discussions. 我确定没有重复的issue或讨论。

  • [X] I'm sure it's due to AList and not something else(such as Network ,Dependencies or Operational). 我确定是AList的问题,而不是其他原因(例如网络依赖操作)。

  • [X] I'm sure this issue is not fixed in the latest version. 我确定这个问题在最新版本中没有被修复。

AList Version / AList 版本

v3.35.0

Driver used / 使用的存储驱动

123pan

Describe the bug / 问题描述

这个问题之前有人提出过,但是当时认为是缓存问题 希望可以在页面上手动清理缓存 这里在描述一次,复现步骤如下:

  1. A,B服务共用数据库
  2. A中新增存储F,B在存储管理里面刷新列表,可以看到A新增的F,但是在文件列表刷新,无法看到存储F挂载的目录,必须要重启B的alist服务才可以
  3. 同理,如果A,B都有存储F,A中删除存储F,B中文件列表也不会删除F的挂载目录

Reproduction / 复现链接

问题已经定位到了,原因如下:

  1. 获取存储列表是直接从数据库获取的,所以每次获取存储列表都是最新的
  2. 获取文件列表时,使用的是内存中的storagesMap变量,而内存是和服务器绑定的,所以就导致获取文件列表使用的不是最新的
  3. 本来通过存储管理界面的Relaod All按钮可以更新内存中的storagesMap,但是更新出现了问题 func LoadAllStorages(c *gin.Context) { storages, err := db.GetEnabledStorages() if err != nil { log.Errorf("failed get enabled storages: %+v", err) common.ErrorResp(c, err, 500, true) return } conf.StoragesLoaded = false go func(storages []model.Storage) { //这里的更新逻辑是:先卸载存储,再挂载 //而storages是从数据库获取的,这就意味着,A服务删除了存储F,在B服务更新时, //只会更新存在的,而F不在数据库中,也就不会动F,所以更新后,F依然存在storagesMap中 //A中新增存储F时,B中更新会先从storagesMap中查询F的挂载目录,查询不到,直接报错…… //这个逻辑有问题,本身就是要更新storagesMap,却使用了旧的storagesMap查询…… for _, storage := range storages { storageDriver, err := op.GetStorageByMountPath(storage.MountPath) if err != nil { log.Errorf("failed get storage driver: %+v", err) continue } // drop the storage in the driver if err := storageDriver.Drop(context.Background()); err != nil { log.Errorf("failed drop storage: %+v", err) continue } if err := op.LoadStorage(context.Background(), storage); err != nil { log.Errorf("failed get enabled storages: %+v", err) continue } log.Infof("success load storage: [%s], driver: [%s]", storage.MountPath, storage.Driver) } conf.StoragesLoaded = true }(storages) common.SuccessResp(c) }

Config / 配置

Logs / 日志

[GIN] 2024/07/21 - 02:43:16 | 200 | 28.722787ms | 192.168.31.40 | POST "/api/admin/storage/load_all" [36mINFO[0m[2024-07-21 02:43:17] success load storage: [/123pan4764], driver: [123Pan] [36mINFO[0m[2024-07-21 02:43:17] success load storage: [/crypt123pan4764], driver: [Crypt] [36mINFO[0m[2024-07-21 02:43:18] success load storage: [/baidubdusername], driver: [BaiduNetdisk] [36mINFO[0m[2024-07-21 02:43:18] success load storage: [/baiduluopo], driver: [BaiduNetdisk] [36mINFO[0m[2024-07-21 02:43:18] success load storage: [/cryptBdLp], driver: [Crypt] [36mINFO[0m[2024-07-21 02:43:19] success load storage: [/123panlu], driver: [123Pan] [36mINFO[0m[2024-07-21 02:43:19] success load storage: [/crypt123panlu], driver: [Crypt] [36mINFO[0m[2024-07-21 02:43:19] success load storage: [/local_us], driver: [Local] [31mERRO[0m[2024-07-21 02:43:19] failed get storage driver: no mount path for an storage is: /ali github.com/alist-org/alist/v3/internal/op.GetStorageByMountPath /home/sfy/work/alist/internal/op/storage.go:37 github.com/alist-org/alist/v3/server/handles.LoadAllStorages.func1 /home/sfy/work/alist/server/handles/storage.go:135 runtime.goexit /usr/local/go/src/runtime/asm_amd64.s:1650

ForSourceCodeAnalysis avatar Jul 21 '24 06:07 ForSourceCodeAnalysis