我有以下代码:
package publicservice
import (
"time"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/testutil"
"testing"
)
func TestAcquireLock(t *testing.T) {
consul := testutil.NewTestServer(t)
defer consul.Stop()
firstClient, err := api.NewClient(&api.Config{
Address: consul.HTTPAddr,
})
if err != nil {
t.Fatalf("failed to create first client with %v", err)
}
secondClient, err := api.NewClient(&api.Config{
Address: consul.HTTPAddr,
})
if err != nil {
t.Fatalf("failed to create second client with %v", err)
}
lockKey := "sample-lock-key"
firstLock, err := firstClient.LockOpts(&api.LockOptions{
Key: lockKey,
})
if err != nil {
t.Fatalf("failed to create first lock %v", err)
}
_, err = firstLock.Lock(nil)
if err != nil {
t.Fatalf("failed to acquire first lock %v", err)
}
defer firstLock.Unlock()
secondLock, err := secondClient.LockOpts(&api.LockOptions{
Key: lockKey,
LockTryOnce: true,
LockWaitTime: time.Second,
})
if err != nil {
t.Fatalf("failed to create second lock %v", err)
}
_, err = secondLock.Lock(nil)
if err == nil {
t.Fatal("should not have acquired lock here")
}
}
而且当我运行它时,第二次锁调用永远不会失败,即使它应该失败,因为该锁已经被另一个客户端持有,如日志所示:
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/catalog/nodes (1.115897356s) from=127.0.0.1:50492
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/session/create (939.436µs) from=127.0.0.1:50493
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?wait=15000ms (269.823µs) from=127.0.0.1:50493
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/kv/sample-lock-key?acquire=aa8fb351-6b6e-8e17-f8d9-fb265c497a9f&flags=3304740253564472344 (899.564µs) from=127.0.0.1:50493
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?consistent= (112.87µs) from=127.0.0.1:50493
2016/11/29 14:46:25 [DEBUG] http: Request PUT /v1/session/create (595.554µs) from=127.0.0.1:50494
2016/11/29 14:46:25 [DEBUG] http: Request GET /v1/kv/sample-lock-key?wait=1000ms (38.602µs) from=127.0.0.1:50494
2016/11/29 14:46:26 [DEBUG] http: Request GET /v1/kv/sample-lock-key?index=7&wait=999ms (1.007117154s) from=127.0.0.1:50494
2016/11/29 14:46:26 [DEBUG] http: Request PUT /v1/session/destroy/fd83b8f8-1757-d9d7-6f0e-5defaf26b886 (1.549558ms) from=127.0.0.1:50494
2016/11/29 14:46:26 [DEBUG] http: Request PUT /v1/kv/sample-lock-key?flags=3304740253564472344&release=aa8fb351-6b6e-8e17-f8d9-fb265c497a9f (1.56451ms) from=127.0.0.1:50495
2016/11/29 14:46:26 [DEBUG] http: Request GET /v1/kv/sample-lock-key?consistent=&index=7 (1.010637359s) from=127.0.0.1:50493
我在这里想念什么?我还必须执行其他操作以确保第二个客户端没有获得该锁吗?
最佳答案
问题是您必须检查从Lock
返回的 channel ,如果该锁已经被持有,则该 channel 是nil
:
package publicservice
import (
"time"
"github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/testutil"
"testing"
"github.com/xtgo/uuid"
)
func TestAcquireLock(t *testing.T) {
consul := testutil.NewTestServer(t)
defer consul.Stop()
firstClient, err := api.NewClient(&api.Config{
Address: consul.HTTPAddr,
})
if err != nil {
t.Fatalf("failed to create first client with %v", err)
}
secondClient, err := api.NewClient(&api.Config{
Address: consul.HTTPAddr,
})
if err != nil {
t.Fatalf("failed to create second client with %v", err)
}
lockKey := "sample-lock-key"
firstLock, err := firstClient.LockOpts(&api.LockOptions{
Key: lockKey,
SessionName: uuid.NewRandom().String(),
})
if err != nil {
t.Fatalf("failed to create first lock %v", err)
}
firstResult, err := firstLock.Lock(nil)
t.Logf("=====> result for first lock is %v", firstResult)
if err != nil {
t.Fatalf("failed to acquire first lock %v", err)
}
defer firstLock.Unlock()
secondLock, err := secondClient.LockOpts(&api.LockOptions{
Key: lockKey,
LockTryOnce: true,
LockWaitTime: time.Second,
SessionName: uuid.NewRandom().String(),
})
if err != nil {
t.Fatalf("failed to create second lock %v", err)
}
secondResult, err := secondLock.Lock(nil)
if secondResult != nil || err != nil {
t.Fatal("should not have acquired lock here")
}
}