mirror of
https://github.com/hanzoai/insights-go.git
synced 2026-09-30 22:46:12 +00:00
Import order only, one line per file. These sat unformatted because fmt.yml filtered on pushes to `main` while this repo's default branch is `master`, so the check had nothing to look at on the branch every commit lands on. With the filter corrected the gate ran and named them immediately.
141 lines
3.4 KiB
Go
141 lines
3.4 KiB
Go
package extras
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
|
|
insights "github.com/hanzoai/insights-go"
|
|
"github.com/orian/flakyhttp"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestRetryBehavior(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
failCount int // 0 = always fail, N = fail N times then succeed
|
|
requestCount int
|
|
disableRetry bool // if true, RetryAfter returns -1
|
|
expectSuccess bool
|
|
retryAfter func(i int) time.Duration
|
|
forceClose bool
|
|
}{
|
|
{
|
|
name: "NoRetry_DropsMessage",
|
|
failCount: 0, // always fail
|
|
requestCount: 1,
|
|
disableRetry: true,
|
|
expectSuccess: false,
|
|
},
|
|
{
|
|
name: "AllRetriesFail_DropsMessage",
|
|
failCount: 0, // always fail, will exhaust all 10 retries
|
|
requestCount: 10,
|
|
disableRetry: false,
|
|
expectSuccess: false,
|
|
},
|
|
{
|
|
name: "QuitDuringRetry_DropsMessage",
|
|
failCount: 1, // always fail, will exhaust all 10 retries
|
|
requestCount: 1,
|
|
disableRetry: false,
|
|
expectSuccess: false,
|
|
retryAfter: func(i int) time.Duration {
|
|
return time.Minute
|
|
},
|
|
forceClose: true,
|
|
},
|
|
{
|
|
name: "SuccessOnLastRetry",
|
|
failCount: 9, // fail 9 times, succeed on 10th (last retry)
|
|
requestCount: 10,
|
|
disableRetry: false,
|
|
expectSuccess: true,
|
|
},
|
|
}
|
|
|
|
for _, tc := range tests {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
server := flakyhttp.NewServer(flakyhttp.Config{
|
|
Scenario: flakyhttp.ScenarioNoResponse,
|
|
FailCount: tc.failCount,
|
|
})
|
|
|
|
url, err := server.Start()
|
|
require.NoError(t, err)
|
|
defer server.Close()
|
|
|
|
callback := newTestCallback(t)
|
|
|
|
config := insights.Config{
|
|
Endpoint: url,
|
|
Transport: &timeoutTransport{
|
|
rt: http.DefaultTransport,
|
|
timeout: 1 * time.Second,
|
|
},
|
|
Interval: 1 * time.Millisecond,
|
|
BatchSize: 1,
|
|
Logger: insights.StdLogger(log.New(os.Stderr, "[insights] ", log.LstdFlags), true),
|
|
Callback: callback,
|
|
RetryAfter: func(i int) time.Duration { return time.Millisecond },
|
|
}
|
|
|
|
if tc.disableRetry {
|
|
config.MaxRetries = insights.Ptr[int](0)
|
|
}
|
|
if tc.retryAfter != nil {
|
|
config.RetryAfter = tc.retryAfter
|
|
}
|
|
|
|
client, err := insights.NewWithConfig("test-api-key", config)
|
|
require.NoError(t, err)
|
|
|
|
err = client.Enqueue(insights.Capture{
|
|
DistinctId: "user1",
|
|
Event: "test_event",
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
if tc.forceClose {
|
|
time.Sleep(10 * time.Millisecond)
|
|
client.Close()
|
|
}
|
|
|
|
// Wait for callback
|
|
select {
|
|
case <-callback.successChan:
|
|
if !tc.expectSuccess {
|
|
require.Fail(t, "Expected failure but got success")
|
|
}
|
|
t.Log("Event delivered successfully")
|
|
case err := <-callback.failureChan:
|
|
if tc.expectSuccess {
|
|
require.Fail(t, "Expected success but got failure: %v", err)
|
|
}
|
|
t.Logf("Event dropped as expected: %v", err)
|
|
case <-time.After(5 * time.Second):
|
|
require.Fail(t, "Timeout waiting for callback")
|
|
}
|
|
|
|
if !tc.forceClose {
|
|
client.Close()
|
|
}
|
|
|
|
success, failure := callback.GetCounts()
|
|
assert.Equal(t, tc.requestCount, server.RequestCount())
|
|
assert.Equal(t, 1, success+failure, "Expected 1 callback")
|
|
|
|
if tc.expectSuccess {
|
|
assert.Equal(t, 1, success, "Expected 1 success")
|
|
assert.Equal(t, 0, failure, "Expected 0 failures")
|
|
} else {
|
|
assert.Equal(t, 0, success, "Expected 0 success")
|
|
assert.Equal(t, 1, failure, "Expected 1 failure")
|
|
}
|
|
})
|
|
}
|
|
}
|