解决哪吒面板删除服务器后 ID 不连续

1、问题描述

本来以为哪吒面板删除服务器后会自动对其进行重新排序,结果确实会1,代码如下:

Go
1
2
3
4
5
6
7
if err == nil {
    // 删除服务器
    singleton.ServerLock.Lock()
    onServerDelete(id)
    singleton.ServerLock.Unlock()
    singleton.ReSortServer()
}

然而删除之后 ID 还是不连续的,这让我强迫症犯了非常的难受,而且后台显示不连续就算了,访客查看居然也是不连续的(使用 Neko-Mdui 主题,其他主题不显示服务器 ID,可能没有这个困扰)。

2、代码分析

问题出在哪里呢?我们来看看 ReSortServer 方法,根据说明实现了一个排序功能:

ReSortServer 根据服务器ID 对服务器列表进行排序(ID越大越靠前)。2

代码如下:

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
func ReSortServer() {
    ServerLock.RLock()
    defer ServerLock.RUnlock()
    SortedServerLock.Lock()
    defer SortedServerLock.Unlock()

    SortedServerList = []*model.Server{}
    SortedServerListForGuest = []*model.Server{}
    for _, s := range ServerList {
    SortedServerList = append(SortedServerList, s)
    if !s.HideForGuest {
        SortedServerListForGuest = append(SortedServerListForGuest, s)
        }
    }

    // 按照服务器 ID 排序的具体实现(ID越大越靠前)
    sort.SliceStable(SortedServerList, func(i, j int) bool {
    if SortedServerList[i].DisplayIndex == SortedServerList[j].DisplayIndex {
        return SortedServerList[i].ID < SortedServerList[j].ID
    }
    return SortedServerList[i].DisplayIndex > SortedServerList[j].DisplayIndex
    })

    sort.SliceStable(SortedServerListForGuest, func(i, j int) bool {
    if SortedServerListForGuest[i].DisplayIndex == SortedServerListForGuest[j].DisplayIndex {
        return SortedServerListForGuest[i].ID < SortedServerListForGuest[j].ID
    }
    return SortedServerListForGuest[i].DisplayIndex > SortedServerListForGuest[j].DisplayIndex
    })
}

嗯,没学过 Golang 看不懂,但是大致可以根据命名看出这个方法仅对列表进行排序,并不重新设置 ID。

3、解决方法

直接编辑 /opt/nezha/dashboard/data/sqlite.db,执行:

sql
1
2
3
4
5
6
UPDATE servers
SET id = (
    SELECT COUNT(*) 
    FROM servers AS s 
    WHERE s.rowid <= servers.rowid
);

即可解决。

4、花絮

根据面向 ChatGPT 编程深入研究,最早得出的 SQL 语句是:

sql
1
2
3
4
5
6
7
8
9
10
-- 创建临时表,并按照原始id的顺序填充连续的序列号
WITH RankedServers AS (
  SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS NewId
  FROM servers
)
-- 使用UPDATE语句将servers表中的id更新为连续的序列号
UPDATE servers
SET id = RankedServers.NewId
FROM RankedServers
WHERE servers.id = RankedServers.id;

然而执行后直接报错语法错误,打回去让 GPT 重写

sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 创建一个临时表来存储原始id和新的连续id
CREATE TEMP TABLE TempServers AS
SELECT id, ROW_NUMBER() OVER (ORDER BY id) AS NewId
FROM servers;

-- 删除原始表中的数据
DELETE FROM servers;

-- 将临时表中的数据插入原始表中
INSERT INTO servers(id, other_columns)
SELECT NewId, other_columns
FROM TempServers;

-- 删除临时表
DROP TABLE TempServers;

还是不行,最后强调是 SQLite 环境后才得出上述可以运行的代码。

然后根据哪吒面板的代码,可以再加上:

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
func UpdateServersID() {
    ServerLock.Lock()
    defer ServerLock.Unlock()

    for i, s := range ServerList {
        count := 0
        for _, s2 := range ServerList[:i+1] {
            if s2.RowID <= s.RowID {
                count++
            }
        }
        s.ID = count
    }
}

实现 ID 重设,但是我没有 Golang 调试环境,就不去瞎改代码了(XD),有能力的可以参考此段代码去提个 Pull Request。


  1. member_api.go 第 205 行
  2. singleton package 页面

解决哪吒面板删除服务器后 ID 不连续

https://blog.tsinbei.com/archives/1501/

文章作者
Hsukqi Lee
发布于

2024-04-06

修改于

2024-04-06

许可协议

CC BY-NC-ND 4.0

# 学习  建站  编程  SQL  网站  Linux  软件  SQLite  数据库  Go

评论

昵称
邮箱
网址
暂无