diff --git a/pkg/atproto/atproto.go b/pkg/atproto/atproto.go index dd2b3de8..b3042706 100644 --- a/pkg/atproto/atproto.go +++ b/pkg/atproto/atproto.go @@ -349,6 +349,9 @@ func (atsync *ATProtoSynchronizer) RefreshIdentity(ctx context.Context, did stri if err != nil { return nil, fmt.Errorf("failed to update repo: %w", err) } + // Drop the cached identity so subsequent cached resolves pick up the new + // PDS/handle instead of serving the stale entry for up to 24h. + atsync.purgeIdentCache(ctx, id.DID.String()) return id, nil } diff --git a/pkg/atproto/refresh_identity_test.go b/pkg/atproto/refresh_identity_test.go new file mode 100644 index 00000000..a7bf6a20 --- /dev/null +++ b/pkg/atproto/refresh_identity_test.go @@ -0,0 +1,43 @@ +package atproto + +import ( + "context" + "testing" + + "github.com/bluesky-social/indigo/atproto/identity" + "github.com/bluesky-social/indigo/atproto/syntax" + "github.com/stretchr/testify/require" + "stream.place/streamplace/pkg/devenv" +) + +// TestRefreshIdentityPurgesCache proves that RefreshIdentity drops the cached +// identity entry, so the next cached resolve picks up a new PDS/handle instead +// of serving a stale entry for up to 24h. Without the purge, a PDS migration +// would leave every cached resolve pointing at the dead host. +func TestRefreshIdentityPurgesCache(t *testing.T) { + dev := devenv.WithDevEnv(t) + ctx := context.Background() + atsync, _ := backfillTestSynchronizer(t, dev) + user := dev.CreateAccount(t) + + // Warm the cache with a cached resolve. + _, err := atsync.resolveIdent(ctx, user.DID, true) + require.NoError(t, err) + + did, err := syntax.ParseDID(user.DID) + require.NoError(t, err) + + cd, ok := atsync.directory(true).(*identity.CacheDirectory) + require.True(t, ok) + _, hit, err := cd.LookupDIDWithCacheState(ctx, did) + require.NoError(t, err) + require.True(t, hit, "cache should be warm before refresh") + + // RefreshIdentity should purge the cached entry. + _, err = atsync.RefreshIdentity(ctx, user.DID) + require.NoError(t, err) + + _, hit, err = cd.LookupDIDWithCacheState(ctx, did) + require.NoError(t, err) + require.False(t, hit, "RefreshIdentity should purge the cached identity") +}