- Introduced a new Diagnostics struct to capture transaction visibility state and activity state. - Updated BuildSnapshot function to return diagnostics alongside snapshot, completeness, and sampling. - Enhanced test cases to validate the new diagnostics data. - Updated frontend components to utilize the new diagnostics information for improved user feedback on freshness context. This change improves the observability of transaction activity and enhances the user experience by providing clearer insights into the freshness of data.
236 lines
6.7 KiB
Go
236 lines
6.7 KiB
Go
package freshness
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/jackc/pgx/v5"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type fakeRow struct {
|
|
scan func(dest ...any) error
|
|
}
|
|
|
|
func (r fakeRow) Scan(dest ...any) error {
|
|
return r.scan(dest...)
|
|
}
|
|
|
|
func TestBuildSnapshotHealthyState(t *testing.T) {
|
|
now := time.Date(2026, 4, 10, 22, 10, 16, 0, time.UTC)
|
|
call := 0
|
|
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
|
|
call++
|
|
switch call {
|
|
case 1:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 200
|
|
*dest[1].(*time.Time) = now.Add(-2 * time.Second)
|
|
return nil
|
|
}}
|
|
case 2:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*string) = "0xabc"
|
|
*dest[1].(*int64) = 198
|
|
*dest[2].(*time.Time) = now.Add(-5 * time.Second)
|
|
return nil
|
|
}}
|
|
case 3:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 198
|
|
*dest[1].(*time.Time) = now.Add(-5 * time.Second)
|
|
return nil
|
|
}}
|
|
case 4:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 198
|
|
*dest[1].(*time.Time) = now.Add(-5 * time.Second)
|
|
return nil
|
|
}}
|
|
case 5:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 128
|
|
*dest[1].(*int64) = 12
|
|
*dest[2].(*int64) = 34
|
|
return nil
|
|
}}
|
|
default:
|
|
t.Fatalf("unexpected call %d", call)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
probe := func(context.Context) (*Reference, error) {
|
|
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
|
|
age := int64(1)
|
|
block := int64(200)
|
|
return &Reference{
|
|
BlockNumber: &block,
|
|
Timestamp: &ts,
|
|
AgeSeconds: &age,
|
|
Source: SourceReported,
|
|
Confidence: ConfidenceHigh,
|
|
Provenance: ProvenanceRPC,
|
|
Completeness: CompletenessComplete,
|
|
}, nil
|
|
}
|
|
|
|
snapshot, completeness, sampling, diagnostics, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, int64(200), *snapshot.ChainHead.BlockNumber)
|
|
require.Equal(t, int64(198), *snapshot.LatestIndexedTransaction.BlockNumber)
|
|
require.Equal(t, int64(2), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
|
|
require.Equal(t, CompletenessComplete, completeness.TransactionsFeed)
|
|
require.NotNil(t, sampling.StatsGeneratedAt)
|
|
require.Equal(t, "active", diagnostics.ActivityState)
|
|
}
|
|
|
|
func TestBuildSnapshotFreshHeadStaleTransactionVisibility(t *testing.T) {
|
|
now := time.Date(2026, 4, 11, 0, 10, 16, 0, time.UTC)
|
|
call := 0
|
|
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
|
|
call++
|
|
switch call {
|
|
case 1:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3875999
|
|
*dest[1].(*time.Time) = now.Add(-3 * time.Second)
|
|
return nil
|
|
}}
|
|
case 2:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*string) = "0xstale"
|
|
*dest[1].(*int64) = 3860660
|
|
*dest[2].(*time.Time) = now.Add(-(9*time.Hour + 8*time.Minute))
|
|
return nil
|
|
}}
|
|
case 3:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3860660
|
|
*dest[1].(*time.Time) = now.Add(-(9*time.Hour + 8*time.Minute))
|
|
return nil
|
|
}}
|
|
case 4:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3875998
|
|
*dest[1].(*time.Time) = now.Add(-4 * time.Second)
|
|
return nil
|
|
}}
|
|
case 5:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 128
|
|
*dest[1].(*int64) = 3
|
|
*dest[2].(*int64) = 9
|
|
return nil
|
|
}}
|
|
default:
|
|
t.Fatalf("unexpected call %d", call)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
probe := func(context.Context) (*Reference, error) {
|
|
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
|
|
age := int64(1)
|
|
block := int64(3876000)
|
|
return &Reference{
|
|
BlockNumber: &block,
|
|
Timestamp: &ts,
|
|
AgeSeconds: &age,
|
|
Source: SourceReported,
|
|
Confidence: ConfidenceHigh,
|
|
Provenance: ProvenanceRPC,
|
|
Completeness: CompletenessComplete,
|
|
}, nil
|
|
}
|
|
|
|
snapshot, completeness, _, diagnostics, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, int64(15340), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
|
|
require.Equal(t, CompletenessStale, completeness.TransactionsFeed)
|
|
require.Equal(t, CompletenessComplete, completeness.BlocksFeed)
|
|
require.Equal(t, "fresh_head_stale_transaction_visibility", diagnostics.ActivityState)
|
|
}
|
|
|
|
func TestBuildSnapshotQuietChainButCurrent(t *testing.T) {
|
|
now := time.Date(2026, 4, 10, 23, 10, 16, 0, time.UTC)
|
|
call := 0
|
|
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
|
|
call++
|
|
switch call {
|
|
case 1:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3875000
|
|
*dest[1].(*time.Time) = now.Add(-1 * time.Second)
|
|
return nil
|
|
}}
|
|
case 2:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*string) = "0xquiet"
|
|
*dest[1].(*int64) = 3874902
|
|
*dest[2].(*time.Time) = now.Add(-512 * time.Second)
|
|
return nil
|
|
}}
|
|
case 3:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3874902
|
|
*dest[1].(*time.Time) = now.Add(-512 * time.Second)
|
|
return nil
|
|
}}
|
|
case 4:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 3874902
|
|
*dest[1].(*time.Time) = now.Add(-512 * time.Second)
|
|
return nil
|
|
}}
|
|
case 5:
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
*dest[0].(*int64) = 128
|
|
*dest[1].(*int64) = 0
|
|
*dest[2].(*int64) = 0
|
|
return nil
|
|
}}
|
|
default:
|
|
t.Fatalf("unexpected call %d", call)
|
|
return nil
|
|
}
|
|
}
|
|
|
|
probe := func(context.Context) (*Reference, error) {
|
|
ts := now.Add(-1 * time.Second).Format(time.RFC3339)
|
|
age := int64(1)
|
|
block := int64(3875000)
|
|
return &Reference{
|
|
BlockNumber: &block,
|
|
Timestamp: &ts,
|
|
AgeSeconds: &age,
|
|
Source: SourceReported,
|
|
Confidence: ConfidenceHigh,
|
|
Provenance: ProvenanceRPC,
|
|
Completeness: CompletenessComplete,
|
|
}, nil
|
|
}
|
|
|
|
snapshot, completeness, _, diagnostics, err := BuildSnapshot(context.Background(), 138, queryRow, probe, now, nil, nil)
|
|
require.NoError(t, err)
|
|
require.Equal(t, int64(98), *snapshot.LatestNonEmptyBlock.DistanceFromHead)
|
|
require.Equal(t, CompletenessComplete, completeness.TransactionsFeed)
|
|
require.Equal(t, "quiet_chain", diagnostics.ActivityState)
|
|
}
|
|
|
|
func TestBuildSnapshotUnknownFieldsRemainNullSafe(t *testing.T) {
|
|
queryRow := func(_ context.Context, _ string, _ ...any) pgx.Row {
|
|
return fakeRow{scan: func(dest ...any) error {
|
|
return pgx.ErrNoRows
|
|
}}
|
|
}
|
|
|
|
snapshot, completeness, sampling, diagnostics, err := BuildSnapshot(context.Background(), 138, queryRow, nil, time.Now().UTC(), nil, nil)
|
|
require.NoError(t, err)
|
|
require.Nil(t, snapshot.ChainHead.BlockNumber)
|
|
require.Equal(t, CompletenessUnavailable, completeness.TransactionsFeed)
|
|
require.NotNil(t, sampling.StatsGeneratedAt)
|
|
require.Equal(t, "limited_observability", diagnostics.ActivityState)
|
|
}
|