lock
API
lock
packageAPI reference for the lock
package.
Imports
(4)
I
interface
Locker
Locker defines the interface for distributed or local locks.
pkg/lock/locker.go:15-25
type Locker interface
Example
// Assuming a RedisLocker implementation
locker := NewRedisLocker(redisClient)
locker.Acquire(ctx, "my-resource", 5*time.Second)
S
struct
InMemoryLocker
InMemoryLocker implements Locker using in-process mutexes.
pkg/lock/memory.go:10-13
type InMemoryLocker struct
Methods
Acquire
Method
Parameters
Returns
error
func (*InMemoryLocker) Acquire(ctx context.Context, key string, ttl time.Duration) error
{
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
for {
ok, err := l.TryLock(ctx, key, ttl)
if err != nil {
return err
}
if ok {
return nil
}
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
}
}
}
TryLock
Method
Parameters
Returns
bool
error
func (*InMemoryLocker) TryLock(_ context.Context, key string, _ time.Duration) (bool, error)
{
l.mu.Lock()
defer l.mu.Unlock()
if _, exists := l.locks[key]; exists {
return false, nil
}
l.locks[key] = struct{}{}
return true, nil
}
Release
Method
Parameters
key
string
Returns
error
func (*InMemoryLocker) Release(_ context.Context, key string) error
{
l.mu.Lock()
defer l.mu.Unlock()
delete(l.locks, key)
return nil
}
Fields
| Name | Type | Description |
|---|---|---|
| mu | sync.Mutex | |
| locks | map[string]struct{} |
F
function
NewInMemoryLocker
NewInMemoryLocker creates a new in-process Locker.
Returns
pkg/lock/memory.go:16-20
func NewInMemoryLocker() *InMemoryLocker
{
return &InMemoryLocker{
locks: make(map[string]struct{}),
}
}
F
function
TestInMemoryLocker_TryLock
Parameters
t
pkg/lock/memory_test.go:10-27
func TestInMemoryLocker_TryLock(t *testing.T)
{
l := NewInMemoryLocker()
ok, err := l.TryLock(context.Background(), "key1", 0)
if err != nil {
t.Fatalf("TryLock failed: %v", err)
}
if !ok {
t.Fatal("expected lock acquired")
}
ok, err = l.TryLock(context.Background(), "key1", 0)
if err != nil {
t.Fatalf("TryLock second call: %v", err)
}
if ok {
t.Fatal("expected lock not acquired (already held)")
}
}
F
function
TestInMemoryLocker_Release
Parameters
t
pkg/lock/memory_test.go:29-45
func TestInMemoryLocker_Release(t *testing.T)
{
l := NewInMemoryLocker()
l.TryLock(context.Background(), "k", 0)
err := l.Release(context.Background(), "k")
if err != nil {
t.Fatalf("Release failed: %v", err)
}
ok, err := l.TryLock(context.Background(), "k", 0)
if err != nil {
t.Fatalf("TryLock after release: %v", err)
}
if !ok {
t.Fatal("expected lock acquired after release")
}
}
F
function
TestInMemoryLocker_Acquire
Parameters
t
pkg/lock/memory_test.go:47-68
func TestInMemoryLocker_Acquire(t *testing.T)
{
l := NewInMemoryLocker()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
l.TryLock(context.Background(), "shared", 0)
time.Sleep(50 * time.Millisecond)
l.Release(context.Background(), "shared")
}()
time.Sleep(5 * time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
err := l.Acquire(ctx, "shared", 0)
if err != nil {
t.Fatalf("Acquire failed: %v", err)
}
wg.Wait()
}
F
function
TestInMemoryLocker_AcquireContextCancel
Parameters
t
pkg/lock/memory_test.go:70-81
func TestInMemoryLocker_AcquireContextCancel(t *testing.T)
{
l := NewInMemoryLocker()
l.TryLock(context.Background(), "blocked", 0)
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Millisecond)
defer cancel()
err := l.Acquire(ctx, "blocked", 0)
if err == nil {
t.Fatal("expected error from cancelled context")
}
}
F
function
TestInMemoryLocker_DifferentKeys
Parameters
t
pkg/lock/memory_test.go:83-90
func TestInMemoryLocker_DifferentKeys(t *testing.T)
{
l := NewInMemoryLocker()
ok1, _ := l.TryLock(context.Background(), "a", 0)
ok2, _ := l.TryLock(context.Background(), "b", 0)
if !ok1 || !ok2 {
t.Fatal("different keys should not conflict")
}
}