mirror of
https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin.git
synced 2026-10-17 23:19:37 +02:00
Traefik runs the plugin under yaegi, which shares the case list of a select statement between every goroutine that runs it. Both ticker loops ran the same select, so when the tickers fired together one loop could end up waiting on the other's channel, dropping stream ticks for up to two metrics intervals. Range over the ticker channel instead, which yaegi evaluates per execution. The stop channel was never used. Fixes #377 Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
38 lines
913 B
Go
38 lines
913 B
Go
package crowdsec_bouncer_traefik_plugin //nolint:revive,stylecheck
|
|
|
|
import (
|
|
"sync"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func sendTicks(ticks chan time.Time, count int) {
|
|
for i := 0; i < count; i++ { //nolint:intrange
|
|
ticks <- time.Time{}
|
|
}
|
|
}
|
|
|
|
func Test_runTicker_keepsEachTickerOnItsOwnChannel(t *testing.T) {
|
|
const count = 20000
|
|
var streamRuns, metricsRuns int64
|
|
var runs sync.WaitGroup
|
|
runs.Add(2 * count)
|
|
streamTicks := make(chan time.Time)
|
|
metricsTicks := make(chan time.Time)
|
|
go runTicker(streamTicks, func() {
|
|
atomic.AddInt64(&streamRuns, 1)
|
|
runs.Done()
|
|
})
|
|
go runTicker(metricsTicks, func() {
|
|
atomic.AddInt64(&metricsRuns, 1)
|
|
runs.Done()
|
|
})
|
|
go sendTicks(streamTicks, count)
|
|
go sendTicks(metricsTicks, count)
|
|
runs.Wait()
|
|
if streamRuns != count || metricsRuns != count {
|
|
t.Errorf("runTicker ran stream %d and metrics %d times, want %d each", streamRuns, metricsRuns, count)
|
|
}
|
|
}
|