rate tracker problem

This commit is contained in:
blindlobstar 2025-04-08 20:18:42 +02:00
parent d7f6343df1
commit 8f17fc60ba
5 changed files with 155 additions and 0 deletions

View File

@ -0,0 +1,7 @@
# Rate Tracker
You are given a `Handler` with a method `Handle()` that performs some work. Your task is to implement the `LogRate` method, which reports how many times `Handle()` is called during each time interval of duration `d`.
The `LogRate` method should periodically report the number of `Handle()` calls that occurred in each interval by calling `monitor.SendRate(int)`.
## Tags
`Concurrency`

View File

@ -0,0 +1,29 @@
package main
import (
"sync/atomic"
"time"
)
type Monitor interface {
SendRate(int)
}
type Handler struct {
cnt atomic.Int32
}
func (h *Handler) Handle() {
// Some work
// Calculate rate of this function
h.cnt.Add(1)
}
func (h *Handler) LogRate(monitor Monitor, d time.Duration) {
go func() {
for range time.After(d) {
cnt := h.cnt.Swap(0)
monitor.SendRate(int(cnt))
}
}()
}

19
13-rate-tracker/task.go Normal file
View File

@ -0,0 +1,19 @@
package main
import (
"time"
)
type Monitor interface {
SendRate(int)
}
type Handler struct{}
func (h *Handler) Handle() {
// Some work
// Calculate rate of this function
}
func (h *Handler) LogRate(monitor Monitor, d time.Duration) {
}

View File

@ -0,0 +1,99 @@
package main
import (
"reflect"
"sync"
"testing"
"time"
)
type mockMonitor struct {
mu sync.Mutex
rateValues []int
}
func newMockMonitor() *mockMonitor {
return &mockMonitor{
rateValues: make([]int, 0),
}
}
func (m *mockMonitor) SendRate(rate int) {
m.mu.Lock()
defer m.mu.Unlock()
m.rateValues = append(m.rateValues, rate)
}
func (m *mockMonitor) GetRateValues() []int {
m.mu.Lock()
defer m.mu.Unlock()
result := make([]int, len(m.rateValues))
copy(result, m.rateValues)
return result
}
func TestHandler(t *testing.T) {
tests := []struct {
name string
handlerCalls int
tickDuration time.Duration
monitoringTime time.Duration
expectedRates []int
}{
{
name: "No calls",
handlerCalls: 0,
tickDuration: 100 * time.Millisecond,
monitoringTime: 250 * time.Millisecond,
expectedRates: []int{0, 0},
},
{
name: "Single call",
handlerCalls: 1,
tickDuration: 100 * time.Millisecond,
monitoringTime: 250 * time.Millisecond,
expectedRates: []int{1, 0},
},
{
name: "Multiple calls",
handlerCalls: 1000,
tickDuration: 100 * time.Millisecond,
monitoringTime: 250 * time.Millisecond,
expectedRates: []int{1000, 0},
},
{
name: "Custom tick duration",
handlerCalls: 5,
tickDuration: 200 * time.Millisecond,
monitoringTime: 450 * time.Millisecond,
expectedRates: []int{5, 0},
},
{
name: "Cancel stops monitoring",
handlerCalls: 5,
tickDuration: 100 * time.Millisecond,
monitoringTime: 150 * time.Millisecond,
expectedRates: []int{5},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
h := &Handler{}
monitor := newMockMonitor()
for range tt.handlerCalls {
go func() {
h.Handle()
}()
}
time.Sleep(tt.monitoringTime)
rateValues := monitor.GetRateValues()
if reflect.DeepEqual(rateValues, tt.expectedRates) {
t.Errorf("Expected: %v, got: %v", tt.expectedRates, rateValues)
}
})
}
}

View File

@ -30,6 +30,7 @@ Here is a list of the problems available in the repository. Problems are organiz
* [Concurrent Queue](10-concurrent-queue/)
* [Concurrent Queue II](11-concurrent-queue-ii/)
* [Concurrent Queue III](12-concurrent-queue-iii/)
* [Rate Tracker](13-rate-tracker/)
## Contributing