Fixed issue with throttling go routine not terminating.
This commit is contained in:
parent
911dd40858
commit
c3e77e6ef3
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"git.wamblee.org/converge/pkg/models"
|
"git.wamblee.org/converge/pkg/models"
|
||||||
"git.wamblee.org/converge/pkg/support/throttling"
|
"git.wamblee.org/converge/pkg/support/throttling"
|
||||||
"time"
|
"time"
|
||||||
@ -17,7 +18,8 @@ func NewStateNotifier(minDelay time.Duration) *StateNotifier {
|
|||||||
webNotificationChannel: make(chan *models.State),
|
webNotificationChannel: make(chan *models.State),
|
||||||
prometheusNotificationChannel: make(chan *models.State),
|
prometheusNotificationChannel: make(chan *models.State),
|
||||||
}
|
}
|
||||||
notifier.throttler = throttling.NewAsyncThrottler(func(state *models.State) {
|
// Runs indefinitely, context does not need to be canceled.
|
||||||
|
notifier.throttler = throttling.NewAsyncThrottler(context.Background(), func(state *models.State) {
|
||||||
notifier.webNotificationChannel <- state
|
notifier.webNotificationChannel <- state
|
||||||
notifier.prometheusNotificationChannel <- state
|
notifier.prometheusNotificationChannel <- state
|
||||||
}, minDelay, 1*time.Second)
|
}, minDelay, 1*time.Second)
|
||||||
|
@ -84,9 +84,10 @@ func (sessions *WebSessions) NewSession(ctx context.Context, cancel context.Canc
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
throttler := throttling.NewAsyncThrottler(func(state *models.State) {
|
throttler := throttling.NewAsyncThrottler(ctx, func(state *models.State) {
|
||||||
session.notifications <- state
|
session.notifications <- state
|
||||||
}, 500*time.Millisecond, 500*time.Millisecond)
|
}, 500*time.Millisecond, 500*time.Millisecond)
|
||||||
|
defer cancel()
|
||||||
for {
|
for {
|
||||||
// the web app opens one websocket connection and sends a hello
|
// the web app opens one websocket connection and sends a hello
|
||||||
// message asking for the latest state when a page is loaded that requires this.
|
// message asking for the latest state when a page is loaded that requires this.
|
||||||
@ -97,7 +98,6 @@ func (sessions *WebSessions) NewSession(ctx context.Context, cancel context.Canc
|
|||||||
throttler.Notify(sessions.lastNotification)
|
throttler.Notify(sessions.lastNotification)
|
||||||
} else {
|
} else {
|
||||||
log.Printf("Got error reading %v", err)
|
log.Printf("Got error reading %v", err)
|
||||||
cancel()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,23 +8,21 @@ import (
|
|||||||
type AsyncThrottler[T any] struct {
|
type AsyncThrottler[T any] struct {
|
||||||
throttler Throttler[T]
|
throttler Throttler[T]
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
|
||||||
events chan *T
|
events chan *T
|
||||||
ticker *time.Ticker
|
ticker *time.Ticker
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAsyncThrottler[T any](notifier func(t *T),
|
func NewAsyncThrottler[T any](ctx context.Context, notifier func(t *T),
|
||||||
minDelay time.Duration,
|
minDelay time.Duration,
|
||||||
pollInterval time.Duration) *AsyncThrottler[T] {
|
pollInterval time.Duration) *AsyncThrottler[T] {
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
throttler := AsyncThrottler[T]{
|
throttler := AsyncThrottler[T]{
|
||||||
throttler: NewThrottler[T](notifier, minDelay),
|
throttler: NewThrottler[T](notifier, minDelay),
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
|
||||||
events: make(chan *T),
|
events: make(chan *T),
|
||||||
ticker: time.NewTicker(pollInterval),
|
ticker: time.NewTicker(pollInterval),
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
defer throttler.ticker.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@ -42,8 +40,3 @@ func NewAsyncThrottler[T any](notifier func(t *T),
|
|||||||
func (throttler *AsyncThrottler[T]) Notify(value *T) {
|
func (throttler *AsyncThrottler[T]) Notify(value *T) {
|
||||||
throttler.events <- value
|
throttler.events <- value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (throttler *AsyncThrottler[T]) Stop() {
|
|
||||||
throttler.cancel()
|
|
||||||
throttler.ticker.Stop()
|
|
||||||
}
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package throttling
|
package throttling
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -9,10 +10,11 @@ func (suite *ThrottlerTestSuite) Test_AsyncDeliverOneValue() {
|
|||||||
|
|
||||||
pollInterval := 10 * time.Millisecond
|
pollInterval := 10 * time.Millisecond
|
||||||
|
|
||||||
throttler := NewAsyncThrottler[int](func(v *int) {
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
throttler := NewAsyncThrottler[int](ctx, func(v *int) {
|
||||||
value = *v
|
value = *v
|
||||||
}, time.Second, pollInterval)
|
}, time.Second, pollInterval)
|
||||||
defer throttler.Stop()
|
defer cancel()
|
||||||
|
|
||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
v := 1
|
v := 1
|
||||||
@ -33,10 +35,11 @@ func (suite *ThrottlerTestSuite) Test_AsyncTwoNotificationsInSHortSucessionSecon
|
|||||||
|
|
||||||
pollInterval := 10 * time.Millisecond
|
pollInterval := 10 * time.Millisecond
|
||||||
|
|
||||||
throttler := NewAsyncThrottler[int](func(v *int) {
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
throttler := NewAsyncThrottler[int](ctx, func(v *int) {
|
||||||
value = *v
|
value = *v
|
||||||
}, time.Second, pollInterval)
|
}, time.Second, pollInterval)
|
||||||
defer throttler.Stop()
|
defer cancel()
|
||||||
|
|
||||||
t0 := time.Now()
|
t0 := time.Now()
|
||||||
v1 := 1
|
v1 := 1
|
||||||
|
Loading…
Reference in New Issue
Block a user