three changes 1. bumps the xsync package to v3 2. creates a common package for synced maps 3. replaces all xsync MapOf imports with the new common/syncd package. --- #### Does this PR need a docs update or release note? - [x] ⛔ No #### Type of change - [x] 🧹 Tech Debt/Cleanup #### Test Plan - [x] ⚡ Unit test - [x] 💚 E2E
141 lines
2.7 KiB
Go
141 lines
2.7 KiB
Go
package count
|
|
|
|
import (
|
|
"github.com/puzpuzpuz/xsync/v3"
|
|
)
|
|
|
|
// Bus handles threadsafe counting of arbitrarily keyed metrics.
|
|
type Bus struct {
|
|
parent *Bus
|
|
stats *xsync.MapOf[string, *xsync.Counter]
|
|
}
|
|
|
|
func New() *Bus {
|
|
return &Bus{
|
|
stats: xsync.NewMapOf[string, *xsync.Counter](),
|
|
}
|
|
}
|
|
|
|
// Local generates a bus with a parent link. Any value added to
|
|
// the local instance also updates the parent by the same increment.
|
|
// This allows you to maintain an isolated set of counts for a
|
|
// bounded context while automatically tallying the global total.
|
|
func (b *Bus) Local() *Bus {
|
|
bus := New()
|
|
bus.parent = b
|
|
|
|
return bus
|
|
}
|
|
|
|
func (b *Bus) getCounter(k Key) *xsync.Counter {
|
|
xc, _ := b.stats.LoadOrStore(string(k), xsync.NewCounter())
|
|
return xc
|
|
}
|
|
|
|
// Inc increases the count by 1.
|
|
func (b *Bus) Inc(k Key) int64 {
|
|
if b == nil {
|
|
return -1
|
|
}
|
|
|
|
return b.Add(k, 1)
|
|
}
|
|
|
|
// Add increases the count by n.
|
|
func (b *Bus) Add(k Key, n int64) int64 {
|
|
if b == nil {
|
|
return -1
|
|
}
|
|
|
|
b.getCounter(k).Add(n)
|
|
|
|
if b.parent != nil {
|
|
b.parent.Add(k, n)
|
|
}
|
|
|
|
return b.Get(k)
|
|
}
|
|
|
|
// Get returns the local count.
|
|
func (b *Bus) Get(k Key) int64 {
|
|
if b == nil {
|
|
return -1
|
|
}
|
|
|
|
return b.getCounter(k).Value()
|
|
}
|
|
|
|
// Total returns the global count.
|
|
func (b *Bus) Total(k Key) int64 {
|
|
if b == nil {
|
|
return -1
|
|
}
|
|
|
|
if b.parent != nil {
|
|
return b.parent.Total(k)
|
|
}
|
|
|
|
return b.Get(k)
|
|
}
|
|
|
|
// Values returns a map of all local values.
|
|
// Not a snapshot, and therefore not threadsafe.
|
|
func (b *Bus) Values() map[string]int64 {
|
|
if b == nil {
|
|
return map[string]int64{}
|
|
}
|
|
|
|
m := make(map[string]int64, b.stats.Size())
|
|
|
|
b.stats.Range(func(k string, v *xsync.Counter) bool {
|
|
m[k] = v.Value()
|
|
return true
|
|
})
|
|
|
|
return m
|
|
}
|
|
|
|
// TotalValues returns a map of all global values.
|
|
// Not a snapshot, and therefore not threadsafe.
|
|
func (b *Bus) TotalValues() map[string]int64 {
|
|
if b == nil {
|
|
return map[string]int64{}
|
|
}
|
|
|
|
if b.parent != nil {
|
|
return b.parent.TotalValues()
|
|
}
|
|
|
|
return b.Values()
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// compliance with callbacks and external packages
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// AdderFor returns a func that adds any value of i
|
|
// to the bus using the given key.
|
|
func (b *Bus) AdderFor(k Key) func(i int64) {
|
|
return func(i int64) {
|
|
b.Add(k, i)
|
|
}
|
|
}
|
|
|
|
type plainAdder struct {
|
|
bus *Bus
|
|
}
|
|
|
|
func (pa plainAdder) Add(k string, n int64) {
|
|
if pa.bus == nil {
|
|
return
|
|
}
|
|
|
|
pa.bus.Add(Key(k), n)
|
|
}
|
|
|
|
// PlainAdder provides support to external packages that could take in a count.Bus
|
|
// but don't recognize the `Key` type, and would prefer a string type key.
|
|
func (b *Bus) PlainAdder() *plainAdder {
|
|
return &plainAdder{b}
|
|
}
|