Files
settings/valuemonitor.go
T

82 lines
1.7 KiB
Go
Raw Normal View History

2026-08-17 09:49:50 -04:00
package settings
import (
"errors"
"fmt"
"log"
"sync"
)
type ValueMonitorParseFunc[T any] func(string) (T, error)
type ValueMonitor[T any] struct {
mutex sync.RWMutex
parent *Settings
updates <-chan string
key string
parserFunc ValueMonitorParseFunc[T]
value T
}
func (v *ValueMonitor[T]) GetValue() T {
v.mutex.RLock()
defer v.mutex.RUnlock()
return v.value
}
func (v *ValueMonitor[T]) maintenanceThread() {
ctx := v.parent.context
for {
select {
case <-ctx.Done():
return
case s, ok := <-v.updates:
if !ok {
return
}
t, err := v.parserFunc(s)
if err != nil {
log.Printf("ValueMonitor error parsing key %q value %q from channel: %v\n", v.key, s, err)
continue
}
func() {
v.mutex.RLock()
defer v.mutex.RUnlock()
v.value = t
}()
}
}
}
func NewValueMonitor[T any](settings *Settings, key string, parserFunc ValueMonitorParseFunc[T]) (*ValueMonitor[T], error) {
monitorChannel := make(chan string, 1)
err := settings.RegisterKeyToMonitor(key, monitorChannel)
if err != nil {
close(monitorChannel)
return nil, fmt.Errorf("error registering ValueMonitor %w", err)
}
initialString, ok := <-monitorChannel
if !ok {
close(monitorChannel)
return nil, errors.New("channel closed before reading initial value")
}
parsed, err := parserFunc(initialString)
if err != nil {
close(monitorChannel)
return nil, fmt.Errorf("error parsing initial value from %q: %v", initialString, err)
}
go func() {
<-settings.context.Done()
close(monitorChannel)
}()
results := &ValueMonitor[T]{
parent: settings,
updates: monitorChannel,
key: key,
parserFunc: parserFunc,
value: parsed,
}
go results.maintenanceThread()
return results, nil
}