Skip to content

Commit

Permalink
Clean up unstable profile cache
Browse files Browse the repository at this point in the history
  • Loading branch information
estrattonbailey committed Jan 7, 2025
1 parent e3e62ba commit 2ca99bf
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 49 deletions.
47 changes: 12 additions & 35 deletions src/state/queries/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import {logEvent, LogEvents, toClout} from '#/lib/statsig/statsig'
import {Shadow} from '#/state/cache/types'
import {STALE} from '#/state/queries'
import {resetProfilePostsQueries} from '#/state/queries/post-feed'
import {
unstableCacheProfileView,
useUnstableProfileViewCache,
} from '#/state/queries/unstable-profile-cache'
import * as userActionHistory from '#/state/userActionHistory'
import * as atp from '#/types/atproto'
import {updateProfileShadow} from '../cache/profile-shadow'
Expand All @@ -35,6 +39,12 @@ import {RQKEY as RQKEY_LIST_CONVOS} from './messages/list-conversations'
import {RQKEY as RQKEY_MY_BLOCKED} from './my-blocked-accounts'
import {RQKEY as RQKEY_MY_MUTED} from './my-muted-accounts'

export * from '#/state/queries/unstable-profile-cache'
/**
* @deprecated use {@link unstableCacheProfileView} instead
*/
export const precacheProfile = unstableCacheProfileView

const RQKEY_ROOT = 'profile'
export const RQKEY = (did: string) => [RQKEY_ROOT, did]

Expand All @@ -44,25 +54,15 @@ export const profilesQueryKey = (handles: string[]) => [
handles,
]

const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache'
/**
* We cache multiple profile view types by this query key. If object shapes are
* important, you should validate the type when accessing the data.
*/
export const unstableProfileViewCacheQueryKey = (didOrHandle: string) => [
unstableProfileViewCacheQueryKeyRoot,
didOrHandle,
]

export function useProfileQuery({
did,
staleTime = STALE.SECONDS.FIFTEEN,
}: {
did: string | undefined
staleTime?: number
}) {
const queryClient = useQueryClient()
const agent = useAgent()
const {getUnstableProfile} = useUnstableProfileViewCache()
return useQuery<AppBskyActorDefs.ProfileViewDetailed>({
// WARNING
// this staleTime is load-bearing
Expand All @@ -77,11 +77,7 @@ export function useProfileQuery({
},
placeholderData: () => {
if (!did) return

// This can return any profile view type
return queryClient.getQueryData<atp.profile.AnyProfileView>(
unstableProfileViewCacheQueryKey(did),
) as AppBskyActorDefs.ProfileViewDetailed
return getUnstableProfile(did) as AppBskyActorDefs.ProfileViewDetailed
},
enabled: !!did,
})
Expand Down Expand Up @@ -512,25 +508,6 @@ function useProfileUnblockMutation() {
})
}

/**
* This function is used to precache a profile view in the query client. Any
* profile view type is accepted, so you should validate the type when
* accessing the data.
*/
export function precacheProfile(
queryClient: QueryClient,
profile: atp.profile.AnyProfileView,
) {
queryClient.setQueryData(
unstableProfileViewCacheQueryKey(profile.handle),
profile,
)
queryClient.setQueryData(
unstableProfileViewCacheQueryKey(profile.did),
profile,
)
}

async function whenAppViewReady(
agent: BskyAgent,
actor: string,
Expand Down
18 changes: 4 additions & 14 deletions src/state/queries/resolve-uri.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,9 @@
import {AtUri} from '@atproto/api'
import {
QueryClient,
useQuery,
useQueryClient,
UseQueryResult,
} from '@tanstack/react-query'
import {QueryClient, useQuery, UseQueryResult} from '@tanstack/react-query'

import {STALE} from '#/state/queries'
import {useAgent} from '#/state/session'
import * as atp from '#/types/atproto'
import {unstableProfileViewCacheQueryKey} from './profile'
import {useUnstableProfileViewCache} from './profile'

const RQKEY_ROOT = 'resolved-did'
export const RQKEY = (didOrHandle: string) => [RQKEY_ROOT, didOrHandle]
Expand All @@ -29,8 +23,8 @@ export function useResolveUriQuery(uri: string | undefined): UriUseQueryResult {
}

export function useResolveDidQuery(didOrHandle: string | undefined) {
const queryClient = useQueryClient()
const agent = useAgent()
const {getUnstableProfile} = useUnstableProfileViewCache()

return useQuery<string, Error>({
staleTime: STALE.HOURS.ONE,
Expand All @@ -46,11 +40,7 @@ export function useResolveDidQuery(didOrHandle: string | undefined) {
initialData: () => {
// Return undefined if no did or handle
if (!didOrHandle) return

// This can return any profile view type
const profile = queryClient.getQueryData<atp.profile.AnyProfileView>(
unstableProfileViewCacheQueryKey(didOrHandle),
)
const profile = getUnstableProfile(didOrHandle)
return profile?.did
},
enabled: !!didOrHandle,
Expand Down
51 changes: 51 additions & 0 deletions src/state/queries/unstable-profile-cache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {useCallback} from 'react'
import {QueryClient,useQueryClient} from '@tanstack/react-query'

import * as atp from '#/types/atproto'

const unstableProfileViewCacheQueryKeyRoot = 'unstableProfileViewCache'
export const unstableProfileViewCacheQueryKey = (didOrHandle: string) => [
unstableProfileViewCacheQueryKeyRoot,
didOrHandle,
]

/**
* Used as a rough cache of profile views to make loading snappier. This method
* accepts and stores any profile view type by both handle and DID.
*
* Access the cache via {@link useUnstableProfileViewCache}.
*/
export function unstableCacheProfileView(
queryClient: QueryClient,
profile: atp.profile.AnyProfileView,
) {
queryClient.setQueryData(
unstableProfileViewCacheQueryKey(profile.handle),
profile,
)
queryClient.setQueryData(
unstableProfileViewCacheQueryKey(profile.did),
profile,
)
}

/**
* Hook to access the unstable profile view cache. This cache can return ANY
* profile view type, so if the object shape is important, you need to use the
* identity validators shipped in the atproto SDK e.g.
* `AppBskyActorDefs.isValidProfileViewBasic` to confirm before using.
*
* To cache a profile, use {@link unstableCacheProfileView}.
*/
export function useUnstableProfileViewCache() {
const qc = useQueryClient()
const getUnstableProfile = useCallback(
(didOrHandle: string) => {
return qc.getQueryData<atp.profile.AnyProfileView>(
unstableProfileViewCacheQueryKey(didOrHandle),
)
},
[qc],
)
return {getUnstableProfile}
}

0 comments on commit 2ca99bf

Please sign in to comment.