Compare commits
5 Commits
v0.9.5
...
87d1e631f9
| Author | SHA1 | Date | |
|---|---|---|---|
| 87d1e631f9 | |||
|
c98df1b4e7
|
|||
| 7bd605d90f | |||
| 60bec67023 | |||
|
cc33c651cd
|
@@ -16,7 +16,7 @@ require (
|
|||||||
github.com/sparetimecoders/goamqp v0.3.3
|
github.com/sparetimecoders/goamqp v0.3.3
|
||||||
github.com/stretchr/testify v1.11.1
|
github.com/stretchr/testify v1.11.1
|
||||||
github.com/vektah/gqlparser/v2 v2.5.32
|
github.com/vektah/gqlparser/v2 v2.5.32
|
||||||
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.256
|
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.257
|
||||||
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1
|
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1
|
||||||
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.19.4
|
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.19.4
|
||||||
gitlab.com/unboundsoftware/eventsourced/pg v1.18.4
|
gitlab.com/unboundsoftware/eventsourced/pg v1.18.4
|
||||||
@@ -80,7 +80,7 @@ require (
|
|||||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/mod v0.33.0 // indirect
|
golang.org/x/mod v0.33.0 // indirect
|
||||||
golang.org/x/net v0.50.0 // indirect
|
golang.org/x/net v0.51.0 // indirect
|
||||||
golang.org/x/sys v0.41.0 // indirect
|
golang.org/x/sys v0.41.0 // indirect
|
||||||
golang.org/x/text v0.34.0 // indirect
|
golang.org/x/text v0.34.0 // indirect
|
||||||
golang.org/x/tools v0.42.0 // indirect
|
golang.org/x/tools v0.42.0 // indirect
|
||||||
|
|||||||
@@ -198,8 +198,8 @@ github.com/wundergraph/astjson v1.1.0 h1:xORDosrZ87zQFJwNGe/HIHXqzpdHOFmqWgykCLV
|
|||||||
github.com/wundergraph/astjson v1.1.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw=
|
github.com/wundergraph/astjson v1.1.0/go.mod h1:h12D/dxxnedtLzsKyBLK7/Oe4TAoGpRVC9nDpDrZSWw=
|
||||||
github.com/wundergraph/go-arena v1.1.0 h1:9+wSRkJAkA2vbYHp6s8tEGhPViRGQNGXqPHT0QzhdIc=
|
github.com/wundergraph/go-arena v1.1.0 h1:9+wSRkJAkA2vbYHp6s8tEGhPViRGQNGXqPHT0QzhdIc=
|
||||||
github.com/wundergraph/go-arena v1.1.0/go.mod h1:ROOysEHWJjLQ8FSfNxZCziagb7Qw2nXY3/vgKRh7eWw=
|
github.com/wundergraph/go-arena v1.1.0/go.mod h1:ROOysEHWJjLQ8FSfNxZCziagb7Qw2nXY3/vgKRh7eWw=
|
||||||
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.256 h1:IlLfd3qL4THUkxSXsVRwcDNCAPNXqDrflMI0Hbvlb/Q=
|
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.257 h1:hGsaKXRkH3o8DkyizY48/wC1Q+NB1nfD9EKVA7Gc81Y=
|
||||||
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.256/go.mod h1:gfmmrPd2khZONmwYE8RIfnGjwIG+RqL52jYiBzcUST8=
|
github.com/wundergraph/graphql-go-tools/v2 v2.0.0-rc.257/go.mod h1:gfmmrPd2khZONmwYE8RIfnGjwIG+RqL52jYiBzcUST8=
|
||||||
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1 h1:X6269JoAzHIKCVmtgMHZH3m7xOpACSp37ca3eODe9iU=
|
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1 h1:X6269JoAzHIKCVmtgMHZH3m7xOpACSp37ca3eODe9iU=
|
||||||
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1/go.mod h1:EAs0d6Eh0aDiQkUJlSWErHqgHFQdxx0e8I7aG/2FarY=
|
gitlab.com/unboundsoftware/eventsourced/amqp v1.9.1/go.mod h1:EAs0d6Eh0aDiQkUJlSWErHqgHFQdxx0e8I7aG/2FarY=
|
||||||
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.19.4 h1:+yZkhi9/sTyBEN5vJTfvycyXgGrm07QKGSh3jiWiQdM=
|
gitlab.com/unboundsoftware/eventsourced/eventsourced v1.19.4 h1:+yZkhi9/sTyBEN5vJTfvycyXgGrm07QKGSh3jiWiQdM=
|
||||||
@@ -251,8 +251,8 @@ golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
|||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
|||||||
+40
-28
@@ -3,6 +3,7 @@ package graph
|
|||||||
import (
|
import (
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"testing"
|
"testing"
|
||||||
|
"testing/synctest"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -10,48 +11,59 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestDebouncer_Coalesces(t *testing.T) {
|
func TestDebouncer_Coalesces(t *testing.T) {
|
||||||
d := NewDebouncer(50 * time.Millisecond)
|
synctest.Test(t, func(t *testing.T) {
|
||||||
var calls atomic.Int32
|
d := NewDebouncer(50 * time.Millisecond)
|
||||||
|
var calls atomic.Int32
|
||||||
|
|
||||||
// Fire 10 rapid calls for the same key — only the last should execute.
|
// Fire 10 rapid calls for the same key — only the last should execute.
|
||||||
for range 10 {
|
for range 10 {
|
||||||
d.Debounce("key1", func() {
|
d.Debounce("key1", func() {
|
||||||
calls.Add(1)
|
calls.Add(1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the debounce delay plus some margin.
|
// Advance fake clock past the debounce delay and let goroutines settle.
|
||||||
time.Sleep(150 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
synctest.Wait()
|
||||||
|
|
||||||
assert.Equal(t, int32(1), calls.Load(), "rapid calls should coalesce into a single execution")
|
assert.Equal(t, int32(1), calls.Load(), "rapid calls should coalesce into a single execution")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDebouncer_DifferentKeys(t *testing.T) {
|
func TestDebouncer_DifferentKeys(t *testing.T) {
|
||||||
d := NewDebouncer(50 * time.Millisecond)
|
synctest.Test(t, func(t *testing.T) {
|
||||||
var calls atomic.Int32
|
d := NewDebouncer(50 * time.Millisecond)
|
||||||
|
var calls atomic.Int32
|
||||||
|
|
||||||
d.Debounce("key-a", func() { calls.Add(1) })
|
d.Debounce("key-a", func() { calls.Add(1) })
|
||||||
d.Debounce("key-b", func() { calls.Add(1) })
|
d.Debounce("key-b", func() { calls.Add(1) })
|
||||||
d.Debounce("key-c", func() { calls.Add(1) })
|
d.Debounce("key-c", func() { calls.Add(1) })
|
||||||
|
|
||||||
time.Sleep(150 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
synctest.Wait()
|
||||||
|
|
||||||
assert.Equal(t, int32(3), calls.Load(), "different keys should fire independently")
|
assert.Equal(t, int32(3), calls.Load(), "different keys should fire independently")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDebouncer_TimerReset(t *testing.T) {
|
func TestDebouncer_TimerReset(t *testing.T) {
|
||||||
d := NewDebouncer(100 * time.Millisecond)
|
synctest.Test(t, func(t *testing.T) {
|
||||||
var value atomic.Int32
|
d := NewDebouncer(100 * time.Millisecond)
|
||||||
|
var value atomic.Int32
|
||||||
|
|
||||||
// First call sets value to 1.
|
// First call sets value to 1.
|
||||||
d.Debounce("key", func() { value.Store(1) })
|
d.Debounce("key", func() { value.Store(1) })
|
||||||
|
|
||||||
// Wait 60ms (less than the 100ms delay), then replace with value 2.
|
// Advance 60ms (less than the 100ms delay) — first timer hasn't fired.
|
||||||
time.Sleep(60 * time.Millisecond)
|
time.Sleep(60 * time.Millisecond)
|
||||||
d.Debounce("key", func() { value.Store(2) })
|
|
||||||
|
|
||||||
// At 60ms the first timer hasn't fired yet. Wait for the second timer.
|
// Replace with value 2 — resets the timer to fire at 60+100 = 160ms.
|
||||||
time.Sleep(150 * time.Millisecond)
|
d.Debounce("key", func() { value.Store(2) })
|
||||||
|
|
||||||
require.Equal(t, int32(2), value.Load(), "later call should replace the earlier one")
|
// Advance another 100ms (total 160ms) to fire the reset timer.
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
synctest.Wait()
|
||||||
|
|
||||||
|
require.Equal(t, int32(2), value.Load(), "later call should replace the earlier one")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user