44 lines
1.2 KiB
Go
44 lines
1.2 KiB
Go
package main
|
|
|
|
import "sync"
|
|
|
|
// lruSet is a bounded insertion-ordered string set used for event-id dedup and
|
|
// tracking our own sent event ids. Oldest entries evict once cap is reached.
|
|
// Self-locking: events are now processed in concurrent per-message goroutines, so
|
|
// Add/Has must be safe to call from several goroutines at once.
|
|
type lruSet struct {
|
|
mu sync.Mutex
|
|
cap int
|
|
set map[string]struct{}
|
|
order []string
|
|
}
|
|
|
|
func newLRUSet(cap int) *lruSet {
|
|
return &lruSet{cap: cap, set: make(map[string]struct{}, cap), order: make([]string, 0, cap)}
|
|
}
|
|
|
|
func (l *lruSet) Has(k string) bool {
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
_, ok := l.set[k]
|
|
return ok
|
|
}
|
|
|
|
// Add inserts k and returns true if it was newly added (false if already present).
|
|
// The check-and-insert is atomic, so two goroutines racing on the same id can
|
|
// never both get true — the in-memory dedup stays correct under concurrency.
|
|
func (l *lruSet) Add(k string) bool {
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
if _, ok := l.set[k]; ok {
|
|
return false
|
|
}
|
|
if len(l.order) >= l.cap {
|
|
oldest := l.order[0]
|
|
l.order = l.order[1:]
|
|
delete(l.set, oldest)
|
|
}
|
|
l.set[k] = struct{}{}
|
|
l.order = append(l.order, k)
|
|
return true
|
|
}
|