package sync_test import ( "context" "io" "log/slog" "testing" "time" "github.com/jackc/pgx/v5" "github.com/stretchr/testify/require" "git.fabledsword.com/bvandeusen/minstrel/internal/sync" ) // The compactor keeps each entity's latest change however old, so an app // syncing from 0 still gets an artist nobody has touched in months. It drops // what a newer row supersedes, and deletes past their retention, raising the // trimmed mark past the newest delete it dropped. func TestCompact_KeepsEachEntitysLatestChange_Integration(t *testing.T) { pool := testPool(t) ctx := context.Background() old := time.Now().Add(-90 * 24 * time.Hour) recent := time.Now().Add(-time.Hour) add := func(entity, op string, at time.Time) int64 { t.Helper() var id int64 require.NoError(t, pool.QueryRow(ctx, `INSERT INTO library_changes (entity_type, entity_id, op, changed_at) VALUES ('artist', $1, $2, $3) RETURNING id`, entity, op, at).Scan(&id)) return id } untouched := add("untouched", "upsert", old) // kept: latest, however old add("edited", "upsert", old) // dropped: superseded edited := add("edited", "upsert", recent) // kept add("removed-long-ago", "upsert", old) // dropped: superseded removedLongAgo := add("removed-long-ago", "delete", old) // dropped: past retention add("removed-lately", "upsert", old) // dropped: superseded removedLately := add("removed-lately", "delete", recent) // kept: within retention require.NoError(t, sync.Compact(ctx, pool, time.Now().Add(-sync.CompactorRetention), slog.New(slog.NewTextHandler(io.Discard, nil)))) rows, err := pool.Query(ctx, `SELECT id FROM library_changes ORDER BY id`) require.NoError(t, err) left, err := pgx.CollectRows(rows, pgx.RowTo[int64]) require.NoError(t, err) require.Equal(t, []int64{untouched, edited, removedLately}, left) var through int64 require.NoError(t, pool.QueryRow(ctx, `SELECT through FROM library_changes_trimmed`).Scan(&through)) require.Equal(t, removedLongAgo, through, "the trimmed mark stands at the newest dropped delete") // A second pass finds nothing more, and leaves the mark where it is. require.NoError(t, sync.Compact(ctx, pool, time.Now().Add(-sync.CompactorRetention), slog.New(slog.NewTextHandler(io.Discard, nil)))) require.NoError(t, pool.QueryRow(ctx, `SELECT through FROM library_changes_trimmed`).Scan(&through)) require.Equal(t, removedLongAgo, through) }