diff --git a/lock.go b/lock.go index 1eb4268..196fc51 100644 --- a/lock.go +++ b/lock.go @@ -684,6 +684,22 @@ func (c *Client) sUnlock(ctx context.Context, resourceName, lockId string) error return nil } +// Gc removes all lock entries in the collection that have expired +// Specifically this removes lock entries where exclusive.lockId is nil AND shared.count is 0 +func (c *Client) Gc(ctx context.Context) error { + // Get all empty locks and remove + selector := bson.M{ + "exclusive.lockId": nil, + "shared.count": 0, + } + + _, err := c.collection.DeleteMany(ctx, selector) + if err != nil { + return err + } + return nil +} + // lockFromDetails creates a lock struct from a lockId and a LockDetails struct. func lockFromDetails(lockId string, ld LockDetails) lock { now := time.Now() diff --git a/purge.go b/purge.go index b7ed54b..c605ecc 100644 --- a/purge.go +++ b/purge.go @@ -45,6 +45,11 @@ func (p *purger) Purge(ctx context.Context) ([]LockStatus, error) { } allUnlocked = append(allUnlocked, unlocked...) } + // Garbage collect unused lock records + err = p.client.Gc(ctx) + if err != nil { + return allUnlocked, err + } return allUnlocked, nil }