Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 61 additions & 36 deletions cmd/locket/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,11 @@ var _ = Describe("Locket", func() {
Context("when a lock is acquired", func() {
JustBeforeEach(func() {
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
_, err := locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err := locketClient.Lock(context.Background(), lockRequest)
Expect(err).NotTo(HaveOccurred())
})

Expand Down Expand Up @@ -224,10 +225,11 @@ var _ = Describe("Locket", func() {
defer wg.Done()
var err error
for j := 0; j < 3; j++ {
_, err := locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err := locketClient.Lock(context.Background(), lockRequest)
if err == nil {
break
}
Expand Down Expand Up @@ -333,10 +335,11 @@ var _ = Describe("Locket", func() {
_, err := sqlRunner.DB().Exec("DROP TABLE locks")
Expect(err).NotTo(HaveOccurred())
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
_, err = locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err = locketClient.Lock(context.Background(), lockRequest)
Expect(err).To(HaveOccurred())
})

Expand All @@ -349,57 +352,64 @@ var _ = Describe("Locket", func() {
It("locks the key with the corresponding value", func() {
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
expectedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", Type: "lock", TypeCode: models.LOCK}
_, err := locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err := locketClient.Lock(context.Background(), lockRequest)
Expect(err).NotTo(HaveOccurred())

resp, err := locketClient.Fetch(context.Background(), &models.FetchRequest{Key: "test"})
fetchRequest := &models.FetchRequest{Key: "test"}
resp, err := locketClient.Fetch(context.Background(), fetchRequest)
Expect(err).NotTo(HaveOccurred())
Expect(resp.Resource).To(BeEquivalentTo(expectedResource))

requestedResource = &models.Resource{Key: "test", Value: "test-data", Owner: "nima", TypeCode: models.LOCK}
_, err = locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest = &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err = locketClient.Lock(context.Background(), lockRequest)
Expect(err).To(HaveOccurred())
})

It("logs the uuid of the request", func() {
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
ctx := metadata.NewOutgoingContext(context.Background(), metadata.Pairs("uuid", "some-uuid"))
_, err := locketClient.Lock(ctx, &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 10,
})
}
_, err := locketClient.Lock(ctx, lockRequest)
Expect(err).NotTo(HaveOccurred())

Eventually(locketRunner).Should(gbytes.Say("some-uuid"))
})

It("expires after a ttl", func() {
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
_, err := locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 6,
})
}
_, err := locketClient.Lock(context.Background(), lockRequest)
Expect(err).NotTo(HaveOccurred())

Eventually(func() error {
_, err := locketClient.Fetch(context.Background(), &models.FetchRequest{Key: "test"})
fetchRequest := &models.FetchRequest{Key: "test"}
_, err := locketClient.Fetch(context.Background(), fetchRequest)
return err
}, 10*time.Second).Should(HaveOccurred())
})

Context("when the lock server disappears unexpectedly", func() {
It("still disappears after ~ the ttl", func() {
requestedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
_, err := locketClient.Lock(context.Background(), &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: requestedResource,
TtlInSeconds: 3,
})
}
_, err := locketClient.Lock(context.Background(), lockRequest)
Expect(err).NotTo(HaveOccurred())

ginkgomon.Kill(locketProcess)
Expand All @@ -409,7 +419,8 @@ var _ = Describe("Locket", func() {
locketProcess = ginkgomon.Invoke(locketRunner)

Eventually(func() error {
_, err := locketClient.Fetch(context.Background(), &models.FetchRequest{Key: "test"})
fetchRequest := &models.FetchRequest{Key: "test"}
_, err := locketClient.Fetch(context.Background(), fetchRequest)
return err
}, 6*time.Second).Should(HaveOccurred())
})
Expand All @@ -422,7 +433,8 @@ var _ = Describe("Locket", func() {
Context("when the lock does not exist", func() {
It("does not throw an error releasing the lock", func() {
requestedResource = &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
_, err := locketClient.Release(context.Background(), &models.ReleaseRequest{Resource: requestedResource})
releaseRequest := &models.ReleaseRequest{Resource: requestedResource}
_, err := locketClient.Release(context.Background(), releaseRequest)
Expect(err).NotTo(HaveOccurred())
})
})
Expand All @@ -431,26 +443,31 @@ var _ = Describe("Locket", func() {
JustBeforeEach(func() {
requestedResource = &models.Resource{Key: "test", Value: "test-data", Owner: "jim", TypeCode: models.LOCK}
expectedResource := &models.Resource{Key: "test", Value: "test-data", Owner: "jim", Type: "lock", TypeCode: models.LOCK}
_, err := locketClient.Lock(context.Background(), &models.LockRequest{Resource: requestedResource, TtlInSeconds: 10})
lockRequest := &models.LockRequest{Resource: requestedResource, TtlInSeconds: 10}
_, err := locketClient.Lock(context.Background(), lockRequest)
Expect(err).NotTo(HaveOccurred())

resp, err := locketClient.Fetch(context.Background(), &models.FetchRequest{Key: "test"})
fetchRequest := &models.FetchRequest{Key: "test"}
resp, err := locketClient.Fetch(context.Background(), fetchRequest)
Expect(err).NotTo(HaveOccurred())
Expect(resp.Resource).To(BeEquivalentTo(expectedResource))
})

It("releases the lock", func() {
_, err := locketClient.Release(context.Background(), &models.ReleaseRequest{Resource: requestedResource})
releaseRequest := &models.ReleaseRequest{Resource: requestedResource}
_, err := locketClient.Release(context.Background(), releaseRequest)
Expect(err).NotTo(HaveOccurred())

_, err = locketClient.Fetch(context.Background(), &models.FetchRequest{Key: "test"})
fetchRequest := &models.FetchRequest{Key: "test"}
_, err = locketClient.Fetch(context.Background(), fetchRequest)
Expect(err).To(HaveOccurred())
})

Context("when another process is the lock owner", func() {
It("throws an error", func() {
requestedResource = &models.Resource{Key: "test", Value: "test-data", Owner: "nima", TypeCode: models.LOCK}
_, err := locketClient.Release(context.Background(), &models.ReleaseRequest{Resource: requestedResource})
releaseRequest := &models.ReleaseRequest{Resource: requestedResource}
_, err := locketClient.Release(context.Background(), releaseRequest)
Expect(err).To(HaveOccurred())
})
})
Expand All @@ -463,28 +480,33 @@ var _ = Describe("Locket", func() {
)

JustBeforeEach(func() {
_, err := locketClient.Lock(context.Background(), &models.LockRequest{

lock1Request := &models.LockRequest{
Resource: resource1,
TtlInSeconds: 10,
})
}
_, err := locketClient.Lock(context.Background(), lock1Request)
Expect(err).NotTo(HaveOccurred())

_, err = locketClient.Lock(context.Background(), &models.LockRequest{
lock2Request := &models.LockRequest{
Resource: resource2,
TtlInSeconds: 10,
})
}
_, err = locketClient.Lock(context.Background(), lock2Request)
Expect(err).NotTo(HaveOccurred())

_, err = locketClient.Lock(context.Background(), &models.LockRequest{
lock3Request := &models.LockRequest{
Resource: resource3,
TtlInSeconds: 10,
})
}
_, err = locketClient.Lock(context.Background(), lock3Request)
Expect(err).NotTo(HaveOccurred())

_, err = locketClient.Lock(context.Background(), &models.LockRequest{
lock4Request := &models.LockRequest{
Resource: resource4,
TtlInSeconds: 10,
})
}
_, err = locketClient.Lock(context.Background(), lock4Request)
Expect(err).NotTo(HaveOccurred())
})

Expand All @@ -504,13 +526,15 @@ var _ = Describe("Locket", func() {
})

It("fetches all the locks corresponding to type code", func() {
response, err := locketClient.FetchAll(context.Background(), &models.FetchAllRequest{TypeCode: models.LOCK})
fetchAllRequest := &models.FetchAllRequest{TypeCode: models.LOCK}
response, err := locketClient.FetchAll(context.Background(), fetchAllRequest)
Expect(err).NotTo(HaveOccurred())
Expect(response.Resources).To(ConsistOf(expectedResource1, expectedResource2))
})

It("fetches all the presences corresponding to type", func() {
response, err := locketClient.FetchAll(context.Background(), &models.FetchAllRequest{TypeCode: models.PRESENCE})
fetchAllRequest := &models.FetchAllRequest{TypeCode: models.PRESENCE}
response, err := locketClient.FetchAll(context.Background(), fetchAllRequest)
Expect(err).NotTo(HaveOccurred())
Expect(response.Resources).To(ConsistOf(expectedResource3, expectedResource4))
})
Expand All @@ -527,7 +551,8 @@ var _ = Describe("Locket", func() {
JustBeforeEach(func() {
_, err := sqlRunner.DB().Exec("DROP TABLE locks")
Expect(err).NotTo(HaveOccurred())
_, err = locketClient.FetchAll(context.Background(), &models.FetchAllRequest{TypeCode: models.LOCK})
fetchAllRequest := &models.FetchAllRequest{TypeCode: models.LOCK}
_, err = locketClient.FetchAll(context.Background(), fetchAllRequest)
Expect(err).To(HaveOccurred())
})

Expand Down
2 changes: 1 addition & 1 deletion db/dbfakes/fake_lock_db.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 7 additions & 5 deletions db/lock_db.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ func (db *SQLDB) Lock(ctx context.Context, logger lager.Logger, resource *models
if newLock {
_, err = db.helper.Insert(ctx, logger, tx, "locks",
helpers.SQLAttributes{
"path": lock.Key,
"owner": lock.Owner,
"value": lock.Value,
"path": lock.Key,
"owner": lock.Owner,
"value": lock.Value,
//lint:ignore SA1019 - backwards compatibility
"type": lock.Type,
"modified_index": lock.ModifiedIndex,
"modified_id": lock.ModifiedId,
Expand All @@ -70,8 +71,9 @@ func (db *SQLDB) Lock(ctx context.Context, logger lager.Logger, resource *models
} else {
_, err = db.helper.Update(ctx, logger, tx, "locks",
helpers.SQLAttributes{
"owner": lock.Owner,
"value": lock.Value,
"owner": lock.Owner,
"value": lock.Value,
//lint:ignore SA1019 - backwards compatibility
"type": lock.Type,
"modified_index": lock.ModifiedIndex,
"modified_id": lock.ModifiedId,
Expand Down
16 changes: 12 additions & 4 deletions db/lock_db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ func validateLockInDB(rawDB *sql.DB, res *models.Resource, expectedIndex, expect
if res.Value != value {
errMsg += fmt.Sprintf("mismatch value (%s, %s),", res.Value, value)
}
//lint:ignore SA1019 - testing deprecated functionality
if res.Type != lockType {
//lint:ignore SA1019 - testing deprecated functionality
errMsg += fmt.Sprintf("mismatch value (%s, %s),", res.Type, lockType)
}
if expectedIndex != index {
Expand Down Expand Up @@ -83,9 +85,10 @@ var _ = Describe("Lock", func() {
Type: "lock",
}
expectedResource = &models.Resource{
Key: resource.Key,
Owner: resource.Owner,
Value: resource.Value,
Key: resource.Key,
Owner: resource.Owner,
Value: resource.Value,
//lint:ignore SA1019 - testing deprecated functionality
Type: resource.Type,
TypeCode: models.LOCK,
}
Expand Down Expand Up @@ -290,6 +293,7 @@ var _ = Describe("Lock", func() {
`INSERT INTO locks (path, owner, value, type, modified_index, modified_id, ttl) VALUES (?, ?, ?, ?, ?, ?, ?);`,
dbFlavor,
)
//lint:ignore SA1019 - testing deprecated functionality
result, err := rawDB.Exec(query, lock.Key, lock.Owner, lock.Value, lock.Type, 434, "modified-id", 5)
Expect(err).NotTo(HaveOccurred())
Expect(result.RowsAffected()).To(BeEquivalentTo(1))
Expand Down Expand Up @@ -377,6 +381,7 @@ var _ = Describe("Lock", func() {
TypeCode: models.LOCK,
}
expectedLock = lock
//lint:ignore SA1019 - testing deprecated functionality
expectedLock.Type = models.LockType
})

Expand All @@ -401,6 +406,7 @@ var _ = Describe("Lock", func() {
TypeCode: models.PRESENCE,
}
expectedLock = lock
//lint:ignore SA1019 - testing deprecated functionality
expectedLock.Type = models.PresenceType
})

Expand Down Expand Up @@ -554,6 +560,7 @@ var _ = Describe("Lock", func() {
dbFlavor,
)

//lint:ignore SA1019 - testing deprecated functionality
result, err := rawDB.Exec(query, resource.Key, resource.Owner, resource.Value, currentIndex, currentTTL, modifiedId, resource.Type)
Expect(err).NotTo(HaveOccurred())
Expect(result.RowsAffected()).To(BeEquivalentTo(1))
Expand Down Expand Up @@ -643,7 +650,8 @@ var _ = Describe("Lock", func() {
Key: resource.Key,
Owner: "danny",
Value: resource.Value,
Type: resource.Type,
//lint:ignore SA1019 - testing deprecated functionality
Type: resource.Type,
}

released, err := sqlDB.FetchAndRelease(ctx, logger, oldLock)
Expand Down
2 changes: 1 addition & 1 deletion expiration/expirationfakes/fake_lock_pick.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions expiration/lock_pick.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func (l lockPick) ExpirationCounts() (uint32, uint32) {
}

func (l lockPick) RegisterTTL(logger lager.Logger, lock *db.Lock) {
//lint:ignore SA1019 - backwards compatibility
logger = logger.Session("register-ttl", lager.Data{"key": lock.Key, "modified-index": lock.ModifiedIndex, "type": lock.Type})
logger.Debug("starting")
logger.Debug("completed")
Expand Down Expand Up @@ -107,6 +108,7 @@ func (l lockPick) checkExpiration(logger lager.Logger, lock *db.Lock, closeChan
if expired {
logger.Info("lock-expired")
counter := l.locksExpiredCount
//lint:ignore SA1019 - backwards compatibility
if lock.Type == models.PresenceType {
counter = l.presencesExpiredCount
}
Expand Down
4 changes: 3 additions & 1 deletion grpcserver/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ var _ = Describe("GRPCServer", func() {
})
})

type testHandler struct{}
type testHandler struct {
models.UnimplementedLocketServer
}

func (h *testHandler) Lock(ctx context.Context, req *models.LockRequest) (*models.LockResponse, error) {
return &models.LockResponse{}, nil
Expand Down
5 changes: 3 additions & 2 deletions handlers/context_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,11 @@ var _ = Describe("LocketHandler", func() {
finishedRequest := make(chan struct{}, 1)
go func() {
defer GinkgoRecover()
_, err := locketHandler.Lock(ctxWithCancel, &models.LockRequest{
lockRequest := &models.LockRequest{
Resource: resource,
TtlInSeconds: 10,
})
}
_, err := locketHandler.Lock(ctxWithCancel, lockRequest)
Expect(err).To(HaveOccurred())
Expect(err).To(MatchError(context.Canceled))
close(finishedRequest)
Expand Down
Loading