Skip to content

Commit 403e4e9

Browse files
authored
fix(backend): prevent seed opinion creation failure due to read replica lag (#407)
When creating conversations with seed opinions in production, the seed opinion creation was failing with "Conversation slugId not found" errors. This occurred because postNewOpinion queried the conversation by slugId immediately after creation, hitting the read replica before replication completed. Changes: - Add optional conversationMetadata parameter to postNewOpinion interface - When metadata is provided, skip database lookup and use provided values - Skip lock check for seed opinions (just-created conversations cannot be locked) - Pass conversation metadata from createNewPost when creating seed opinions - Eliminates 2 unnecessary database queries per seed opinion This fix resolves the production-only race condition while improving efficiency by avoiding redundant database queries for data already available in scope.
1 parent a91c724 commit 403e4e9

2 files changed

Lines changed: 54 additions & 20 deletions

File tree

services/api/src/service/comment.ts

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,13 @@ interface PostNewOpinionProps {
10901090
userAgent: string;
10911091
now: Date;
10921092
isSeed: boolean;
1093+
conversationMetadata?: {
1094+
conversationId: number;
1095+
conversationContentId: number;
1096+
conversationAuthorId: string;
1097+
conversationIsIndexed: boolean;
1098+
conversationIsLoginRequired: boolean;
1099+
};
10931100
}
10941101

10951102
export async function postNewOpinion({
@@ -1102,31 +1109,51 @@ export async function postNewOpinion({
11021109
userAgent,
11031110
now,
11041111
isSeed,
1112+
conversationMetadata,
11051113
}: PostNewOpinionProps): Promise<CreateCommentResponse> {
1106-
const { getPostMetadataFromSlugId } = useCommonPost();
1107-
const {
1108-
id: conversationId,
1109-
contentId: conversationContentId,
1110-
authorId: conversationAuthorId,
1111-
isIndexed: conversationIsIndexed,
1112-
isLoginRequired: conversationIsLoginRequired,
1113-
} = await getPostMetadataFromSlugId({
1114-
db: db,
1115-
conversationSlugId: conversationSlugId,
1116-
});
1114+
// Use provided metadata if available (for seed opinions), otherwise fetch from DB
1115+
let conversationId: number;
1116+
let conversationContentId: number | null;
1117+
let conversationAuthorId: string;
1118+
let conversationIsIndexed: boolean;
1119+
let conversationIsLoginRequired: boolean;
1120+
1121+
if (conversationMetadata) {
1122+
conversationId = conversationMetadata.conversationId;
1123+
conversationContentId = conversationMetadata.conversationContentId;
1124+
conversationAuthorId = conversationMetadata.conversationAuthorId;
1125+
conversationIsIndexed = conversationMetadata.conversationIsIndexed;
1126+
conversationIsLoginRequired =
1127+
conversationMetadata.conversationIsLoginRequired;
1128+
} else {
1129+
const { getPostMetadataFromSlugId } = useCommonPost();
1130+
const metadata = await getPostMetadataFromSlugId({
1131+
db: db,
1132+
conversationSlugId: conversationSlugId,
1133+
});
1134+
conversationId = metadata.id;
1135+
conversationContentId = metadata.contentId;
1136+
conversationAuthorId = metadata.authorId;
1137+
conversationIsIndexed = metadata.isIndexed;
1138+
conversationIsLoginRequired = metadata.isLoginRequired;
1139+
}
1140+
11171141
if (conversationContentId == null) {
11181142
throw httpErrors.gone("Cannot comment on a deleted post");
11191143
}
11201144

1121-
const isLocked = await useCommonPost().isPostSlugIdLocked({
1122-
postSlugId: conversationSlugId,
1123-
db: db,
1124-
});
1125-
if (isLocked) {
1126-
return {
1127-
success: false,
1128-
reason: "conversation_locked",
1129-
};
1145+
// Skip lock check if metadata provided (seed opinions on just-created conversations)
1146+
if (!conversationMetadata) {
1147+
const isLocked = await useCommonPost().isPostSlugIdLocked({
1148+
postSlugId: conversationSlugId,
1149+
db: db,
1150+
});
1151+
if (isLocked) {
1152+
return {
1153+
success: false,
1154+
reason: "conversation_locked",
1155+
};
1156+
}
11301157
}
11311158

11321159
try {

services/api/src/service/post.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,13 @@ export async function createNewPost({
282282
userAgent: "Seed Opinion Creation",
283283
now,
284284
isSeed: true,
285+
conversationMetadata: {
286+
conversationId,
287+
conversationContentId,
288+
conversationAuthorId: authorId,
289+
conversationIsIndexed: isIndexed,
290+
conversationIsLoginRequired: isIndexed ? true : isLoginRequired,
291+
},
285292
});
286293
}
287294
}

0 commit comments

Comments
 (0)