more
This commit is contained in:
+14
-14
@@ -14,19 +14,23 @@ import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"hash/fnv"
|
||||
"os"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// lockShards bounds the per-key lock memory: keys hash into a fixed set of
|
||||
// mutexes rather than a map that grows with every distinct key ever seen. Two
|
||||
// unrelated keys that collide on a shard serialise occasionally — harmless.
|
||||
const lockShards = 256
|
||||
|
||||
// Store maps an idempotency key to a result id (e.g. an order id), cached in
|
||||
// memory and persisted to an append-only file.
|
||||
type Store struct {
|
||||
mu sync.Mutex
|
||||
m map[string]uint64
|
||||
f *os.File
|
||||
|
||||
klMu sync.Mutex
|
||||
keyLocks map[string]*sync.Mutex
|
||||
mu sync.Mutex
|
||||
m map[string]uint64
|
||||
f *os.File
|
||||
locks [lockShards]sync.Mutex
|
||||
}
|
||||
|
||||
type record struct {
|
||||
@@ -62,7 +66,7 @@ func Open(path string) (*Store, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Store{m: m, f: f, keyLocks: map[string]*sync.Mutex{}}, nil
|
||||
return &Store{m: m, f: f}, nil
|
||||
}
|
||||
|
||||
// Get returns the recorded id for key and whether it was present.
|
||||
@@ -103,13 +107,9 @@ func (s *Store) Lock(key string) func() {
|
||||
if key == "" {
|
||||
return func() {}
|
||||
}
|
||||
s.klMu.Lock()
|
||||
mu, ok := s.keyLocks[key]
|
||||
if !ok {
|
||||
mu = &sync.Mutex{}
|
||||
s.keyLocks[key] = mu
|
||||
}
|
||||
s.klMu.Unlock()
|
||||
h := fnv.New32a()
|
||||
_, _ = h.Write([]byte(key))
|
||||
mu := &s.locks[h.Sum32()%lockShards]
|
||||
mu.Lock()
|
||||
return mu.Unlock
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user