mirror of
https://github.com/henrygd/beszel.git
synced 2025-12-17 02:36:17 +01:00
refactor deltatracker
- embed mutex - add example function
This commit is contained in:
@@ -16,7 +16,7 @@ type Numeric interface {
|
|||||||
// K is the key type (e.g., int, string).
|
// K is the key type (e.g., int, string).
|
||||||
// V is the value type (e.g., int, int64, float32, float64).
|
// V is the value type (e.g., int, int64, float32, float64).
|
||||||
type DeltaTracker[K comparable, V Numeric] struct {
|
type DeltaTracker[K comparable, V Numeric] struct {
|
||||||
mu sync.RWMutex
|
sync.RWMutex
|
||||||
current map[K]V
|
current map[K]V
|
||||||
previous map[K]V
|
previous map[K]V
|
||||||
}
|
}
|
||||||
@@ -31,15 +31,15 @@ func NewDeltaTracker[K comparable, V Numeric]() *DeltaTracker[K, V] {
|
|||||||
|
|
||||||
// Set records the current value for a given ID.
|
// Set records the current value for a given ID.
|
||||||
func (t *DeltaTracker[K, V]) Set(id K, value V) {
|
func (t *DeltaTracker[K, V]) Set(id K, value V) {
|
||||||
t.mu.Lock()
|
t.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.Unlock()
|
||||||
t.current[id] = value
|
t.current[id] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deltas returns a map of all calculated deltas for the current interval.
|
// Deltas returns a map of all calculated deltas for the current interval.
|
||||||
func (t *DeltaTracker[K, V]) Deltas() map[K]V {
|
func (t *DeltaTracker[K, V]) Deltas() map[K]V {
|
||||||
t.mu.RLock()
|
t.RLock()
|
||||||
defer t.mu.RUnlock()
|
defer t.RUnlock()
|
||||||
|
|
||||||
deltas := make(map[K]V)
|
deltas := make(map[K]V)
|
||||||
for id, currentVal := range t.current {
|
for id, currentVal := range t.current {
|
||||||
@@ -55,8 +55,8 @@ func (t *DeltaTracker[K, V]) Deltas() map[K]V {
|
|||||||
// Delta returns the delta for a single key.
|
// Delta returns the delta for a single key.
|
||||||
// Returns 0 if the key doesn't exist or has no previous value.
|
// Returns 0 if the key doesn't exist or has no previous value.
|
||||||
func (t *DeltaTracker[K, V]) Delta(id K) V {
|
func (t *DeltaTracker[K, V]) Delta(id K) V {
|
||||||
t.mu.RLock()
|
t.RLock()
|
||||||
defer t.mu.RUnlock()
|
defer t.RUnlock()
|
||||||
|
|
||||||
currentVal, currentOk := t.current[id]
|
currentVal, currentOk := t.current[id]
|
||||||
if !currentOk {
|
if !currentOk {
|
||||||
@@ -73,8 +73,8 @@ func (t *DeltaTracker[K, V]) Delta(id K) V {
|
|||||||
|
|
||||||
// Cycle prepares the tracker for the next interval.
|
// Cycle prepares the tracker for the next interval.
|
||||||
func (t *DeltaTracker[K, V]) Cycle() {
|
func (t *DeltaTracker[K, V]) Cycle() {
|
||||||
t.mu.Lock()
|
t.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.Unlock()
|
||||||
t.previous = t.current
|
t.previous = t.current
|
||||||
t.current = make(map[K]V)
|
t.current = make(map[K]V)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,28 @@
|
|||||||
|
// Package deltatracker provides a tracker for calculating differences in numeric values over time.
|
||||||
package deltatracker
|
package deltatracker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func ExampleDeltaTracker() {
|
||||||
|
tracker := NewDeltaTracker[string, int]()
|
||||||
|
tracker.Set("key1", 10)
|
||||||
|
tracker.Set("key2", 20)
|
||||||
|
tracker.Cycle()
|
||||||
|
tracker.Set("key1", 15)
|
||||||
|
tracker.Set("key2", 30)
|
||||||
|
fmt.Println(tracker.Delta("key1"))
|
||||||
|
fmt.Println(tracker.Delta("key2"))
|
||||||
|
fmt.Println(tracker.Deltas())
|
||||||
|
// Output: 5
|
||||||
|
// 10
|
||||||
|
// map[key1:5 key2:10]
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewDeltaTracker(t *testing.T) {
|
func TestNewDeltaTracker(t *testing.T) {
|
||||||
tracker := NewDeltaTracker[string, int]()
|
tracker := NewDeltaTracker[string, int]()
|
||||||
assert.NotNil(t, tracker)
|
assert.NotNil(t, tracker)
|
||||||
@@ -17,8 +34,8 @@ func TestSet(t *testing.T) {
|
|||||||
tracker := NewDeltaTracker[string, int]()
|
tracker := NewDeltaTracker[string, int]()
|
||||||
tracker.Set("key1", 10)
|
tracker.Set("key1", 10)
|
||||||
|
|
||||||
tracker.mu.RLock()
|
tracker.RLock()
|
||||||
defer tracker.mu.RUnlock()
|
defer tracker.RUnlock()
|
||||||
|
|
||||||
assert.Equal(t, 10, tracker.current["key1"])
|
assert.Equal(t, 10, tracker.current["key1"])
|
||||||
}
|
}
|
||||||
@@ -55,21 +72,21 @@ func TestCycle(t *testing.T) {
|
|||||||
tracker.Set("key2", 20)
|
tracker.Set("key2", 20)
|
||||||
|
|
||||||
// Verify current has values
|
// Verify current has values
|
||||||
tracker.mu.RLock()
|
tracker.RLock()
|
||||||
assert.Equal(t, 10, tracker.current["key1"])
|
assert.Equal(t, 10, tracker.current["key1"])
|
||||||
assert.Equal(t, 20, tracker.current["key2"])
|
assert.Equal(t, 20, tracker.current["key2"])
|
||||||
assert.Empty(t, tracker.previous)
|
assert.Empty(t, tracker.previous)
|
||||||
tracker.mu.RUnlock()
|
tracker.RUnlock()
|
||||||
|
|
||||||
tracker.Cycle()
|
tracker.Cycle()
|
||||||
|
|
||||||
// After cycle, previous should have the old current values
|
// After cycle, previous should have the old current values
|
||||||
// and current should be empty
|
// and current should be empty
|
||||||
tracker.mu.RLock()
|
tracker.RLock()
|
||||||
assert.Empty(t, tracker.current)
|
assert.Empty(t, tracker.current)
|
||||||
assert.Equal(t, 10, tracker.previous["key1"])
|
assert.Equal(t, 10, tracker.previous["key1"])
|
||||||
assert.Equal(t, 20, tracker.previous["key2"])
|
assert.Equal(t, 20, tracker.previous["key2"])
|
||||||
tracker.mu.RUnlock()
|
tracker.RUnlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompleteWorkflow(t *testing.T) {
|
func TestCompleteWorkflow(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user