Skip to content

Commit 5d2946d

Browse files
authored
feat: implement distributed lock by gorm (#1432)
1 parent 82e2512 commit 5d2946d

17 files changed

Lines changed: 1274 additions & 0 deletions

File tree

app/dubbo-admin/cmd/run.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/apache/dubbo-admin/pkg/config/app"
3131
"github.com/apache/dubbo-admin/pkg/core/bootstrap"
3232
"github.com/apache/dubbo-admin/pkg/core/logger"
33+
_ "github.com/apache/dubbo-admin/pkg/lock/gorm"
3334
dubboversion "github.com/apache/dubbo-admin/pkg/version"
3435
)
3536

pkg/common/bizerror/error.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const (
4646
YamlError ErrorCode = "YamlError"
4747
NotFoundError ErrorCode = "NotFoundError"
4848
NetWorkError ErrorCode = "NetWorkError"
49+
LockNotHeld ErrorCode = "LockNotHeld"
50+
LockExpired ErrorCode = "LockExpired"
4951
)
5052

5153
type bizError struct {

pkg/common/constants/lock.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package constants
19+
20+
import "time"
21+
22+
const (
23+
// DefaultLockTimeout is the default timeout for distributed lock operations
24+
// This timeout applies to lock acquisition, renewal, and release operations
25+
DefaultLockTimeout = 30 * time.Second
26+
27+
// DefaultAutoRenewThreshold is the TTL threshold above which auto-renewal is enabled
28+
// Locks with TTL longer than this value will be automatically renewed
29+
DefaultAutoRenewThreshold = 10 * time.Second
30+
31+
// DefaultUnlockTimeout is the timeout for unlock operations in deferred cleanup
32+
DefaultUnlockTimeout = 5 * time.Second
33+
34+
// DefaultRenewTimeout is the timeout for lock renewal operations
35+
DefaultRenewTimeout = 5 * time.Second
36+
37+
// DefaultLockRetryInterval is the interval between lock acquisition retry attempts
38+
DefaultLockRetryInterval = 100 * time.Millisecond
39+
40+
// DefaultCleanupInterval is the interval for periodic expired lock cleanup
41+
DefaultCleanupInterval = 5 * time.Minute
42+
43+
// DefaultCleanupTimeout is the timeout for cleanup operations
44+
DefaultCleanupTimeout = 30 * time.Second
45+
)
46+
47+
// Lock key prefixes for different resource types
48+
const (
49+
// TagRouteKeyPrefix is the prefix for tag route lock keys
50+
TagRouteKeyPrefix = "tag_route"
51+
52+
// ConfiguratorRuleKeyPrefix is the prefix for configurator rule lock keys
53+
ConfiguratorRuleKeyPrefix = "configurator_rule"
54+
55+
// ConditionRuleKeyPrefix is the prefix for condition rule lock keys
56+
ConditionRuleKeyPrefix = "condition_rule"
57+
)

pkg/console/context/context.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package context
1919

2020
import (
2121
ctx "context"
22+
"github.com/apache/dubbo-admin/pkg/core/lock"
2223

2324
"github.com/apache/dubbo-admin/pkg/config/app"
2425
"github.com/apache/dubbo-admin/pkg/console/counter"
@@ -33,6 +34,7 @@ type Context interface {
3334
Config() app.AdminConfig
3435

3536
AppContext() ctx.Context
37+
LockManager() lock.Lock
3638
}
3739

3840
var _ Context = &context{}
@@ -71,3 +73,11 @@ func (c *context) CounterManager() counter.CounterManager {
7173
}
7274
return managerComp.CounterManager()
7375
}
76+
77+
func (c *context) LockManager() lock.Lock {
78+
distributedLock, err := lock.GetLockFromRuntime(c.coreRt)
79+
if err != nil {
80+
return nil
81+
}
82+
return distributedLock
83+
}

pkg/console/service/condition_rule.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package service
1919

2020
import (
21+
"github.com/apache/dubbo-admin/pkg/common/constants"
22+
"github.com/apache/dubbo-admin/pkg/core/lock"
2123
"github.com/duke-git/lancet/v2/slice"
2224
"github.com/duke-git/lancet/v2/strutil"
2325

@@ -106,6 +108,17 @@ func GetConditionRule(ctx context.Context, name string, mesh string) (*meshresou
106108
}
107109

108110
func UpdateConditionRule(ctx context.Context, res *meshresource.ConditionRouteResource) error {
111+
lockMgr := ctx.LockManager()
112+
if lockMgr == nil {
113+
return updateConditionRuleUnsafe(ctx, res)
114+
}
115+
lockKey := lock.BuildConditionRuleLockKey(res.Mesh, res.Name)
116+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
117+
return updateConditionRuleUnsafe(ctx, res)
118+
})
119+
}
120+
121+
func updateConditionRuleUnsafe(ctx context.Context, res *meshresource.ConditionRouteResource) error {
109122
if err := ctx.ResourceManager().Update(res); err != nil {
110123
logger.Warnf("update %s condition failed with error: %s", res.Name, err.Error())
111124
return err
@@ -114,6 +127,17 @@ func UpdateConditionRule(ctx context.Context, res *meshresource.ConditionRouteRe
114127
}
115128

116129
func CreateConditionRule(ctx context.Context, res *meshresource.ConditionRouteResource) error {
130+
lockMgr := ctx.LockManager()
131+
if lockMgr == nil {
132+
return createConditionRuleUnsafe(ctx, res)
133+
}
134+
lockKey := lock.BuildConditionRuleLockKey(res.Mesh, res.Name)
135+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
136+
return createConditionRuleUnsafe(ctx, res)
137+
})
138+
}
139+
140+
func createConditionRuleUnsafe(ctx context.Context, res *meshresource.ConditionRouteResource) error {
117141
if err := ctx.ResourceManager().Add(res); err != nil {
118142
logger.Warnf("create %s condition failed with error: %s", res.Name, err.Error())
119143
return err
@@ -122,6 +146,17 @@ func CreateConditionRule(ctx context.Context, res *meshresource.ConditionRouteRe
122146
}
123147

124148
func DeleteConditionRule(ctx context.Context, name string, mesh string) error {
149+
lockMgr := ctx.LockManager()
150+
if lockMgr == nil {
151+
return deleteConditionRuleUnsafe(ctx, name, mesh)
152+
}
153+
lockKey := lock.BuildConditionRuleLockKey(mesh, name)
154+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
155+
return deleteConditionRuleUnsafe(ctx, name, mesh)
156+
})
157+
}
158+
159+
func deleteConditionRuleUnsafe(ctx context.Context, name string, mesh string) error {
125160
if err := ctx.ResourceManager().DeleteByKey(meshresource.ConditionRouteKind, mesh, coremodel.BuildResourceKey(mesh, name)); err != nil {
126161
return err
127162
}

pkg/console/service/configurator_rule.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package service
1919

2020
import (
21+
"github.com/apache/dubbo-admin/pkg/common/constants"
22+
"github.com/apache/dubbo-admin/pkg/core/lock"
2123
"github.com/duke-git/lancet/v2/slice"
2224

2325
"github.com/apache/dubbo-admin/pkg/common/bizerror"
@@ -114,6 +116,17 @@ func GetConfigurator(ctx consolectx.Context, name string, mesh string) (*meshres
114116
}
115117

116118
func UpdateConfigurator(ctx consolectx.Context, res *meshresource.DynamicConfigResource) error {
119+
lockMgr := ctx.LockManager()
120+
if lockMgr == nil {
121+
return updateConfiguratorUnsafe(ctx, res)
122+
}
123+
lockKey := lock.BuildConfiguratorRuleLockKey(res.Mesh, res.Name)
124+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
125+
return updateConfiguratorUnsafe(ctx, res)
126+
})
127+
}
128+
129+
func updateConfiguratorUnsafe(ctx consolectx.Context, res *meshresource.DynamicConfigResource) error {
117130
if err := ctx.ResourceManager().Update(res); err != nil {
118131
logger.Warnf("update %s configurator failed with error: %s", res.Name, err.Error())
119132
return err
@@ -122,6 +135,17 @@ func UpdateConfigurator(ctx consolectx.Context, res *meshresource.DynamicConfigR
122135
}
123136

124137
func CreateConfigurator(ctx consolectx.Context, res *meshresource.DynamicConfigResource) error {
138+
lockMgr := ctx.LockManager()
139+
if lockMgr == nil {
140+
return createConfiguratorUnsafe(ctx, res)
141+
}
142+
lockKey := lock.BuildConfiguratorRuleLockKey(res.Mesh, res.Name)
143+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
144+
return createConfiguratorUnsafe(ctx, res)
145+
})
146+
}
147+
148+
func createConfiguratorUnsafe(ctx consolectx.Context, res *meshresource.DynamicConfigResource) error {
125149
if err := ctx.ResourceManager().Add(res); err != nil {
126150
logger.Warnf("create %s configurator failed with error: %s", res.Name, err.Error())
127151
return err
@@ -130,6 +154,17 @@ func CreateConfigurator(ctx consolectx.Context, res *meshresource.DynamicConfigR
130154
}
131155

132156
func DeleteConfigurator(ctx consolectx.Context, name string, mesh string) error {
157+
lockMgr := ctx.LockManager()
158+
if lockMgr == nil {
159+
return deleteConfiguratorUnsafe(ctx, name, mesh)
160+
}
161+
lockKey := lock.BuildConfiguratorRuleLockKey(mesh, name)
162+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
163+
return deleteConfiguratorUnsafe(ctx, name, mesh)
164+
})
165+
}
166+
167+
func deleteConfiguratorUnsafe(ctx consolectx.Context, name string, mesh string) error {
133168
if err := ctx.ResourceManager().DeleteByKey(meshresource.DynamicConfigKind, mesh, coremodel.BuildResourceKey(mesh, name)); err != nil {
134169
logger.Warnf("delete %s configurator failed with error: %s", name, err.Error())
135170
return err

pkg/console/service/tag_rule.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
package service
1919

2020
import (
21+
"github.com/apache/dubbo-admin/pkg/common/constants"
22+
"github.com/apache/dubbo-admin/pkg/core/lock"
2123
"github.com/duke-git/lancet/v2/slice"
2224

2325
"github.com/apache/dubbo-admin/pkg/common/bizerror"
@@ -112,6 +114,19 @@ func GetTagRule(ctx consolectx.Context, name string, mesh string) (*meshresource
112114
}
113115

114116
func UpdateTagRule(ctx consolectx.Context, res *meshresource.TagRouteResource) error {
117+
lockMgr := ctx.LockManager()
118+
if lockMgr == nil {
119+
return updateTagRuleUnsafe(ctx, res)
120+
}
121+
122+
lockKey := lock.BuildTagRouteLockKey(res.Mesh, res.Name)
123+
124+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
125+
return updateTagRuleUnsafe(ctx, res)
126+
})
127+
}
128+
129+
func updateTagRuleUnsafe(ctx consolectx.Context, res *meshresource.TagRouteResource) error {
115130
err := ctx.ResourceManager().Update(res)
116131
if err != nil {
117132
logger.Warnf("update tag rule %s error: %v", res.Name, err)
@@ -121,6 +136,19 @@ func UpdateTagRule(ctx consolectx.Context, res *meshresource.TagRouteResource) e
121136
}
122137

123138
func CreateTagRule(ctx consolectx.Context, res *meshresource.TagRouteResource) error {
139+
lockMgr := ctx.LockManager()
140+
if lockMgr == nil {
141+
return createTagRuleUnsafe(ctx, res)
142+
}
143+
144+
lockKey := lock.BuildTagRouteLockKey(res.Mesh, res.Name)
145+
146+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
147+
return createTagRuleUnsafe(ctx, res)
148+
})
149+
}
150+
151+
func createTagRuleUnsafe(ctx consolectx.Context, res *meshresource.TagRouteResource) error {
124152
err := ctx.ResourceManager().Add(res)
125153
if err != nil {
126154
logger.Warnf("create tag rule %s error: %v", res.Name, err)
@@ -130,6 +158,17 @@ func CreateTagRule(ctx consolectx.Context, res *meshresource.TagRouteResource) e
130158
}
131159

132160
func DeleteTagRule(ctx consolectx.Context, name string, mesh string) error {
161+
lockMgr := ctx.LockManager()
162+
if lockMgr == nil {
163+
return deleteTagRuleUnsafe(ctx, name, mesh)
164+
}
165+
lockKey := lock.BuildTagRouteLockKey(mesh, name)
166+
return lockMgr.WithLock(ctx.AppContext(), lockKey, constants.DefaultLockTimeout, func() error {
167+
return deleteTagRuleUnsafe(ctx, name, mesh)
168+
})
169+
}
170+
171+
func deleteTagRuleUnsafe(ctx consolectx.Context, name string, mesh string) error {
133172
err := ctx.ResourceManager().DeleteByKey(meshresource.TagRouteKind, mesh, coremodel.BuildResourceKey(mesh, name))
134173
if err != nil {
135174
logger.Warnf("delete tag rule %s error: %v", name, err)

pkg/core/bootstrap/bootstrap.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"github.com/apache/dubbo-admin/pkg/common/bizerror"
2525
"github.com/apache/dubbo-admin/pkg/config/app"
2626
"github.com/apache/dubbo-admin/pkg/console/counter"
27+
"github.com/apache/dubbo-admin/pkg/core/lock"
2728
"github.com/apache/dubbo-admin/pkg/core/logger"
2829
"github.com/apache/dubbo-admin/pkg/core/runtime"
2930
"github.com/apache/dubbo-admin/pkg/diagnostics"
@@ -128,6 +129,7 @@ func (sb *SmartBootstrapper) gatherComponents() ([]runtime.Component, error) {
128129
}{
129130
{"CounterManager", counter.ComponentType},
130131
{"DiagnosticsServer", diagnostics.DiagnosticsServer},
132+
{"DistributedLock", lock.DistributedLockComponent},
131133
}
132134

133135
for _, comp := range optionalComps {

0 commit comments

Comments
 (0)