Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
042d8235
Commit
042d8235
authored
Dec 29, 2025
by
yangjianbo
Browse files
fix(仓储): 修复 ApiKey 更新并发语义
ApiKey 更新时显式设置 updated_at 并回填,避免二次查询竞态 补充软删除范围注释以统一审计语义
parent
74db0c15
Changes
2
Hide whitespace changes
Inline
Side-by-side
backend/internal/repository/api_key_repo.go
View file @
042d8235
...
@@ -91,32 +91,35 @@ func (r *apiKeyRepository) GetByKey(ctx context.Context, key string) (*service.A
...
@@ -91,32 +91,35 @@ func (r *apiKeyRepository) GetByKey(ctx context.Context, key string) (*service.A
}
}
func
(
r
*
apiKeyRepository
)
Update
(
ctx
context
.
Context
,
key
*
service
.
ApiKey
)
error
{
func
(
r
*
apiKeyRepository
)
Update
(
ctx
context
.
Context
,
key
*
service
.
ApiKey
)
error
{
exists
,
err
:=
r
.
activeQuery
()
.
Where
(
apikey
.
IDEQ
(
key
.
ID
))
.
Exist
(
ctx
)
// 使用原子操作:将软删除检查与更新合并到同一语句,避免竞态条件。
if
err
!=
nil
{
// 之前的实现先检查 Exist 再 UpdateOneID,若在两步之间发生软删除,
return
err
// 则会更新已删除的记录。
}
// 这里选择 Update().Where(),确保只有未软删除记录能被更新。
if
!
exists
{
// 同时显式设置 updated_at,避免二次查询带来的并发可见性问题。
return
service
.
ErrApiKeyNotFound
now
:=
time
.
Now
()
}
builder
:=
r
.
client
.
ApiKey
.
Update
()
.
Where
(
apikey
.
IDEQ
(
key
.
ID
),
apikey
.
DeletedAtIsNil
())
.
builder
:=
r
.
client
.
ApiKey
.
UpdateOneID
(
key
.
ID
)
.
SetName
(
key
.
Name
)
.
SetName
(
key
.
Name
)
.
SetStatus
(
key
.
Status
)
SetStatus
(
key
.
Status
)
.
SetUpdatedAt
(
now
)
if
key
.
GroupID
!=
nil
{
if
key
.
GroupID
!=
nil
{
builder
.
SetGroupID
(
*
key
.
GroupID
)
builder
.
SetGroupID
(
*
key
.
GroupID
)
}
else
{
}
else
{
builder
.
ClearGroupID
()
builder
.
ClearGroupID
()
}
}
updated
,
err
:=
builder
.
Save
(
ctx
)
affected
,
err
:=
builder
.
Save
(
ctx
)
if
err
==
nil
{
if
err
!=
nil
{
key
.
UpdatedAt
=
updated
.
UpdatedAt
return
err
return
nil
}
}
if
dbent
.
IsNotFound
(
err
)
{
if
affected
==
0
{
// 更新影响行数为 0,说明记录不存在或已被软删除。
return
service
.
ErrApiKeyNotFound
return
service
.
ErrApiKeyNotFound
}
}
return
err
// 使用同一时间戳回填,避免并发删除导致二次查询失败。
key
.
UpdatedAt
=
now
return
nil
}
}
func
(
r
*
apiKeyRepository
)
Delete
(
ctx
context
.
Context
,
id
int64
)
error
{
func
(
r
*
apiKeyRepository
)
Delete
(
ctx
context
.
Context
,
id
int64
)
error
{
...
...
backend/internal/repository/group_repo.go
View file @
042d8235
...
@@ -289,8 +289,10 @@ func (r *groupRepository) DeleteCascade(ctx context.Context, id int64) ([]int64,
...
@@ -289,8 +289,10 @@ func (r *groupRepository) DeleteCascade(ctx context.Context, id int64) ([]int64,
}
}
// 2. Clear group_id for api keys bound to this group.
// 2. Clear group_id for api keys bound to this group.
// 仅更新未软删除的记录,避免修改已删除数据,保证审计与历史回溯一致性。
// 与 ApiKeyRepository 的软删除语义保持一致,减少跨模块行为差异。
if
_
,
err
:=
txClient
.
ApiKey
.
Update
()
.
if
_
,
err
:=
txClient
.
ApiKey
.
Update
()
.
Where
(
apikey
.
GroupIDEQ
(
id
))
.
Where
(
apikey
.
GroupIDEQ
(
id
)
,
apikey
.
DeletedAtIsNil
()
)
.
ClearGroupID
()
.
ClearGroupID
()
.
Save
(
ctx
);
err
!=
nil
{
Save
(
ctx
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment