Fix optimistic insert

This commit is contained in:
Eric Bailey
2025-05-25 13:41:21 -05:00
parent 8f59675fc4
commit 4c4274ada3
4 changed files with 34 additions and 38 deletions
@@ -33,7 +33,7 @@ export function createCacheMutator({
}) {
return {
insertReplies(
parent: AppBskyUnspeccedGetPostThreadV2.ThreadItem,
parentUri: string,
replies: AppBskyUnspeccedGetPostThreadV2.ThreadItem[],
) {
queryClient.setQueryData<AppBskyUnspeccedGetPostThreadV2.OutputSchema>(
@@ -51,16 +51,14 @@ export function createCacheMutator({
)
)
continue
if (!AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(parent.value))
continue
if (existingParent.uri !== parent.uri) continue
if (existingParent.uri !== parentUri) continue
/*
* Update parent data
*/
existingParent.value.post = {
...existingParent.value.post,
replyCount: parent.value.post.replyCount,
replyCount: (existingParent.value.post.replyCount || 0) + 1,
}
const opDid = getRootPostAtUri(existingParent.value.post)?.host
+1 -6
View File
@@ -27,14 +27,9 @@ export interface ComposerOptsPostRef {
export type OnPostSuccessData =
| {
type: 'post'
replyToUri?: string
posts: AppBskyUnspeccedGetPostThreadV2.ThreadItem[]
}
| {
type: 'reply'
parent: AppBskyUnspeccedGetPostThreadV2.ThreadItem
replies: AppBskyUnspeccedGetPostThreadV2.ThreadItem[]
}
| undefined
export interface ComposerOpts {
+26 -23
View File
@@ -45,6 +45,7 @@ import {type ImagePickerAsset} from 'expo-image-picker'
import {
AppBskyFeedDefs,
type AppBskyFeedGetPostThread,
AppBskyUnspeccedGetPostThreadV2,
type BskyAgent,
type RichText,
} from '@atproto/api'
@@ -393,6 +394,7 @@ export const ComposePost = ({
let postUri: string | undefined
let postSuccessData: OnPostSuccessData
try {
logger.info(`composer: posting...`)
postUri = (
await apilib.post(agent, queryClient, {
thread,
@@ -401,47 +403,48 @@ export const ComposePost = ({
langs: toPostLanguages(langPrefs.postLanguage),
})
).uris[0]
/*
* Wait for app view to have received the post(s). If this fails, it's
* ok, because the post _was_ actually published above.
*/
try {
if (postUri) {
const [maybeParent, maybeReply, ...posts] = await retry(
logger.info(`composer: waiting for app view`)
const posts = await retry(
5,
_e => true,
async () => {
const res = await agent.app.bsky.unspecced.getPostThreadV2({
uri: postUri!,
above: 1,
anchor: postUri!,
above: false,
below: thread.posts.length - 1,
nestedBranchingFactor: 1,
branchingFactor: 1,
})
const parent = res.data.thread.at(0)
if (!parent) {
throw new Error(`Not ready`)
if (res.data.thread.length !== thread.posts.length) {
throw new Error(`composer: app view is not ready`)
}
if (res.data.thread.length !== thread.posts.length + 1) {
throw new Error(`Not ready`)
if (
!res.data.thread.every(p =>
AppBskyUnspeccedGetPostThreadV2.isThreadItemPost(p.value),
)
) {
throw new Error(`composer: app view returned non-post items`)
}
return res.data.thread
},
1e3,
)
if (maybeReply && maybeReply.uri === postUri) {
postSuccessData = {
type: 'reply',
parent: maybeParent,
replies: [maybeReply, ...posts],
}
} else {
postSuccessData = {
type: 'post',
posts: [maybeParent, maybeReply, ...posts].filter(Boolean),
}
postSuccessData = {
replyToUri: replyTo?.uri,
posts,
}
}
} catch (waitErr: any) {
logger.error(waitErr, {
message: `Waiting for app view failed`,
logger.info(`composer: waiting for app view failed`, {
safeMessage: waitErr,
})
// Keep going because the post *was* published.
}
} catch (e: any) {
logger.error(e, {
+4 -4
View File
@@ -151,10 +151,10 @@ export function Inner({uri}: {uri: string | undefined}) {
})
const optimisticOnPostReply = (data: OnPostSuccessData) => {
if (data && data.type === 'reply') {
const {parent, replies} = data
if (parent && replies.length) {
insertReplies(parent, replies)
if (data) {
const {replyToUri, posts} = data
if (replyToUri && posts.length) {
insertReplies(replyToUri, posts)
}
}
}