-
Notifications
You must be signed in to change notification settings - Fork 70
Open
Description
复现步骤
- 创建一个节点,不要添加标签。
- 在订阅中选择该节点,此时拉取订阅是正常的。
- 创建一个新的节点,并且全部添加标签。
- 在订阅中选择该节点标签,拉取订阅时会发现只有之前第一个创建的节点,第二个节点死都无法显示。
原因
在第四步的时候,后端返回的节点列表只有打上标签的部分,此时 subscribe 的 nodes 字段存储了第二个步骤的节点ID,完成第四个步骤后,tags 字段更新成功,但是 nodes 字段并没有清空,因为后端的 update 是默认行为只更新的字段,前端请求的时候只附带了更新的 tag.
server/internal/model/subscribe/default.go
Lines 117 to 130 in a5abbc1
| func (m *defaultSubscribeModel) Update(ctx context.Context, data *Subscribe, tx ...*gorm.DB) error { | |
| old, err := m.FindOne(ctx, data.Id) | |
| if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { | |
| return err | |
| } | |
| err = m.ExecCtx(ctx, func(conn *gorm.DB) error { | |
| db := conn | |
| if len(tx) > 0 { | |
| db = tx[0] | |
| } | |
| return db.Save(data).Error | |
| }, m.getCacheKeys(old)...) | |
| return err | |
| } |
这就导致执行下述代码时候,此时的查询参数 NodeId 和 Tag 都会存在,两个条件会以 AND 关系组合在 SQL 查询中,也就是从指定的节点ID列表中,筛选出包含指定标签的节点,最终返回的只有第一个创建的节点。
server/internal/model/node/model.go
Lines 75 to 112 in a5abbc1
| func (m *customServerModel) FilterNodeList(ctx context.Context, params *FilterNodeParams) (int64, []*Node, error) { | |
| var nodes []*Node | |
| var total int64 | |
| query := m.WithContext(ctx).Model(&Node{}) | |
| if params == nil { | |
| params = &FilterNodeParams{ | |
| Page: 1, | |
| Size: 10, | |
| } | |
| } | |
| if params.Search != "" { | |
| s := "%" + params.Search + "%" | |
| query = query.Where("`name` LIKE ? OR `address` LIKE ? OR `tags` LIKE ? OR `port` LIKE ? ", s, s, s, s) | |
| } | |
| if len(params.NodeId) > 0 { | |
| query = query.Where("id IN ?", params.NodeId) | |
| } | |
| if len(params.ServerId) > 0 { | |
| query = query.Where("server_id IN ?", params.ServerId) | |
| } | |
| if len(params.Tag) > 0 { | |
| query = query.Scopes(InSet("tags", params.Tag)) | |
| } | |
| if params.Protocol != "" { | |
| query = query.Where("protocol = ?", params.Protocol) | |
| } | |
| if params.Enabled != nil { | |
| query = query.Where("enabled = ?", *params.Enabled) | |
| } | |
| if params.Preload { | |
| query = query.Preload("Server") | |
| } | |
| err := query.Count(&total).Order("sort ASC").Limit(params.Size).Offset((params.Page - 1) * params.Size).Find(&nodes).Error | |
| return total, nodes, err | |
| } |
生成 SQL 简单预览
SELECT * FROM nodes
WHERE id IN (node_id_list)
AND (tags字段包含指定的tag)后果
- 后面的新添节点都打上了第三步骤的标签 ,拉取节点列表无论如何都只显示一个节点,也就是第一步创建的节点。
- 从 1.0 迁移 1.1 版本后,因为迁移代码并没有更新
tag只更新了nodes,后续新添节点打上标签,也会遇到这个问题。 - 在订阅中勾选未打上的标签和打上标签的节点,订阅下发时会出现空白。
Metadata
Metadata
Assignees
Labels
No labels