Skip to content

Commit

Permalink
Enhance API functions by adding timeout to record creation, adjusting…
Browse files Browse the repository at this point in the history
… return values for post, vote, and comment retrieval, and ensuring proper async handling in delete operations
  • Loading branch information
WillCorrigan committed Dec 22, 2024
1 parent 4c72496 commit a5a62cf
Show file tree
Hide file tree
Showing 10 changed files with 58 additions and 58 deletions.
7 changes: 5 additions & 2 deletions packages/frontpage/app/(app)/post/new/_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@ export async function newPostAction(_prevState: unknown, formData: FormData) {
}

try {
const { rkey } = await createPost({ title, url, createdAt: new Date() });
const handle = await getVerifiedHandle(user.did);
const [{ rkey }, handle] = await Promise.all([
createPost({ title, url }),
getVerifiedHandle(user.did),
]);

redirect(`/post/${handle}/${rkey}`);
} catch (error) {
if (!(error instanceof DataLayerError)) throw error;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import * as atprotoComment from "../data/atproto/comment";
import { DID } from "../data/atproto/did";
import { Operation } from "../data/atproto/event";
import * as atprotoPost from "../data/atproto/post";
import * as atprotoVote from "../data/atproto/vote";
import * as dbComment from "../data/db/comment";
import * as dbNotification from "../data/db/notification";
import * as dbPost from "../data/db/post";
import * as dbVote from "../data/db/vote";
import { getBlueskyProfile } from "../data/user";
import { sendDiscordMessage } from "../discord";
import { invariant } from "../utils";
import * as atprotoComment from "@/lib/data/atproto/comment";
import { DID } from "@/lib/data/atproto/did";
import { Operation } from "@/lib/data/atproto/event";
import * as atprotoPost from "@/lib/data/atproto/post";
import * as atprotoVote from "@/lib/data/atproto/vote";
import * as dbComment from "@/lib/data/db/comment";
import * as dbNotification from "@/lib/data/db/notification";
import * as dbPost from "@/lib/data/db/post";
import * as dbVote from "@/lib/data/db/vote";
import { getBlueskyProfile } from "@/lib/data/user";
import { sendDiscordMessage } from "@/lib/discord";
import { invariant } from "@/lib/utils";

type HandlerInput = {
op: Zod.infer<typeof Operation>;
Expand All @@ -34,11 +34,12 @@ export async function handlePost({ op, repo, rkey }: HandlerInput) {
const post = await dbPost.uncached_doesPostExist(repo, rkey);

if (!post && postRecord) {
const { title, url, createdAt } = postRecord.value;
const createdDbPost = await dbPost.createPost({
post: {
title: postRecord.title,
url: postRecord.url,
createdAt: new Date(postRecord.createdAt),
title,
url,
createdAt: new Date(createdAt),
},
rkey,
cid: postRecord.cid,
Expand All @@ -52,7 +53,7 @@ export async function handlePost({ op, repo, rkey }: HandlerInput) {
embeds: [
{
title: "New post on Frontpage",
description: postRecord.title,
description: title,
url: `https://frontpage.fyi/post/${repo}/${rkey}`,
color: 10181046,
author: bskyProfile
Expand All @@ -65,7 +66,7 @@ export async function handlePost({ op, repo, rkey }: HandlerInput) {
fields: [
{
name: "Link",
value: postRecord.url,
value: url,
},
],
},
Expand All @@ -92,38 +93,37 @@ export async function handleComment({ op, repo, rkey }: HandlerInput) {
const comment = await dbComment.uncached_doesCommentExist(repo, rkey);

if (!comment && commentRecord) {
const { content, createdAt, parent, post } = commentRecord.value;
const createdComment = await dbComment.createComment({
cid: commentRecord.cid,
authorDid: repo,
rkey,
content: commentRecord.content,
createdAt: new Date(commentRecord.createdAt),
parent: commentRecord.parent
content,
createdAt: new Date(createdAt),
parent: parent
? {
//TODO: is authority a DID?
authorDid: commentRecord.parent.uri.authority as DID,
rkey: commentRecord.parent.uri.rkey,
authorDid: parent.uri.authority as DID,
rkey: parent.uri.rkey,
}
: undefined,
post: {
authorDid: commentRecord.post.uri.authority as DID,
rkey: commentRecord.post.uri.rkey,
authorDid: post.uri.authority as DID,
rkey: post.uri.rkey,
},
});

if (!createdComment) {
throw new Error("Failed to insert comment from relay in database");
}

const didToNotify = commentRecord.parent
? commentRecord.parent.uri.authority
: commentRecord.post.uri.authority;
const didToNotify = parent ? parent.uri.authority : post.uri.authority;

if (didToNotify !== repo) {
await dbNotification.createNotification({
commentId: createdComment.id,
did: didToNotify as DID,
reason: commentRecord.parent ? "commentReply" : "postComment",
reason: parent ? "commentReply" : "postComment",
});
}
}
Expand All @@ -141,7 +141,9 @@ export async function handleVote({ op, repo, rkey }: HandlerInput) {

invariant(hydratedRecord, "atproto vote record not found");

switch (hydratedRecord.subject.uri.collection) {
const { subject } = hydratedRecord.value;

switch (subject.uri.collection) {
case atprotoPost.PostCollection:
const postVote = await dbVote.uncached_doesPostVoteExist(repo, rkey);
if (!postVote) {
Expand All @@ -150,8 +152,8 @@ export async function handleVote({ op, repo, rkey }: HandlerInput) {
rkey,
cid: hydratedRecord.cid,
subject: {
rkey: hydratedRecord.subject.uri.rkey,
authorDid: hydratedRecord.subject.uri.authority as DID,
rkey: subject.uri.rkey,
authorDid: subject.uri.authority as DID,
},
});

Expand All @@ -173,8 +175,8 @@ export async function handleVote({ op, repo, rkey }: HandlerInput) {
rkey,
cid: hydratedRecord.cid,
subject: {
rkey: hydratedRecord.subject.uri.rkey,
authorDid: hydratedRecord.subject.uri.authority as DID,
rkey: subject.uri.rkey,
authorDid: subject.uri.authority as DID,
},
});

Expand All @@ -186,9 +188,7 @@ export async function handleVote({ op, repo, rkey }: HandlerInput) {
}
break;
default:
throw new Error(
`Unknown collection: ${hydratedRecord.subject.uri.collection}`,
);
throw new Error(`Unknown collection: ${subject.uri.collection}`);
}
} else if (op.action === "delete") {
console.log("deleting vote", rkey);
Expand Down
2 changes: 1 addition & 1 deletion packages/frontpage/app/api/receive_hook/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as atprotoPost from "@/lib/data/atproto/post";
import * as atprotoComment from "@/lib/data/atproto/comment";
import * as atprotoVote from "@/lib/data/atproto/vote";
import { getPdsUrl } from "@/lib/data/atproto/did";
import { handleComment, handlePost, handleVote } from "@/lib/api/relayHandler";
import { handleComment, handlePost, handleVote } from "./handlers";
import { eq } from "drizzle-orm";

export async function POST(request: Request) {
Expand Down
8 changes: 5 additions & 3 deletions packages/frontpage/lib/api/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ export async function createComment({

const rkey = TID.next().toString();
try {
const sanitizedContent = content.replace(/\n\n+/g, "\n\n").trim();

const dbCreatedComment = await db.createComment({
cid: "",
authorDid: user.did,
rkey,
content,
content: sanitizedContent,
createdAt: new Date(),
parent,
post,
Expand All @@ -37,7 +39,7 @@ export async function createComment({
const { cid } = await atproto.createComment({
parent,
post,
content,
content: sanitizedContent,
rkey,
});

Expand Down Expand Up @@ -65,8 +67,8 @@ export async function deleteComment({ rkey }: db.DeleteCommentInput) {

try {
console.log("deleteComment", rkey);
await db.deleteComment({ authorDid: user.did, rkey });
await atproto.deleteComment(user.did, rkey);
await db.deleteComment({ authorDid: user.did, rkey });
} catch (e) {
throw new DataLayerError(`Failed to delete comment: ${e}`);
}
Expand Down
13 changes: 4 additions & 9 deletions packages/frontpage/lib/api/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,15 @@ import { TID } from "@atproto/common-web";
export type ApiCreatePostInput = {
title: string;
url: string;
createdAt: Date;
};

export async function createPost({
title,
url,
createdAt,
}: ApiCreatePostInput) {
export async function createPost({ title, url }: ApiCreatePostInput) {
const user = await ensureUser();

const rkey = TID.next().toString();
try {
const dbCreatedPost = await db.createPost({
post: { title, url, createdAt },
post: { title, url, createdAt: new Date() },
rkey,
authorDid: user.did,
});
Expand All @@ -35,7 +30,7 @@ export async function createPost({
rkey,
});

invariant(cid, "Failed to create comment, rkey/cid missing");
invariant(cid, "Failed to create comment, cid missing");

await db.updatePost({ authorDid: user.did, rkey, cid });

Expand Down Expand Up @@ -76,8 +71,8 @@ export async function deletePost({ rkey }: db.DeletePostInput) {
const user = await ensureUser();

try {
await db.deletePost({ authorDid: user.did, rkey });
await atproto.deletePost(user.did, rkey);
await db.deletePost({ authorDid: user.did, rkey });
} catch (e) {
throw new DataLayerError(`Failed to delete post: ${e}`);
}
Expand Down
3 changes: 1 addition & 2 deletions packages/frontpage/lib/api/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ export async function deleteVote({ rkey }: db.DeleteVoteInput) {
const user = await ensureUser();

try {
await db.deleteVote({ authorDid: user.did, rkey });

await atproto.deleteVote(user.did, rkey);
await db.deleteVote({ authorDid: user.did, rkey });
} catch (e) {
throw new DataLayerError(`Failed to delete vote: ${e}`);
}
Expand Down
5 changes: 2 additions & 3 deletions packages/frontpage/lib/data/atproto/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ export async function createComment({
rkey,
}: CommentInput) {
// Collapse newlines into a single \n\n and trim whitespace
const sanitizedContent = content.replace(/\n\n+/g, "\n\n").trim();
const record = {
content: sanitizedContent,
content,
parent: parent
? {
cid: parent.cid,
Expand Down Expand Up @@ -101,5 +100,5 @@ export async function getComment({ rkey, repo }: { rkey: string; repo: DID }) {
rkey,
});

return { ...CommentRecord.parse(value), cid };
return { value: CommentRecord.parse(value), cid };
}
2 changes: 1 addition & 1 deletion packages/frontpage/lib/data/atproto/post.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ export async function getPost({ rkey, repo }: { rkey: string; repo: DID }) {
rkey,
});

return { ...PostRecord.parse(value), cid };
return { value: PostRecord.parse(value), cid };
}
2 changes: 2 additions & 0 deletions packages/frontpage/lib/data/atproto/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export async function atprotoCreateRecord({
validate: false,
record: record,
}),
signal: AbortSignal.timeout(2500),
});

if (!response.ok) {
Expand Down Expand Up @@ -79,6 +80,7 @@ export async function atprotoDeleteRecord({
collection,
rkey,
}),
signal: AbortSignal.timeout(2500),
});

if (!response.ok) {
Expand Down
2 changes: 1 addition & 1 deletion packages/frontpage/lib/data/atproto/vote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,5 @@ export async function getVote({ rkey, repo }: { rkey: string; repo: DID }) {
rkey,
});

return { ...VoteRecord.parse(value), cid };
return { value: VoteRecord.parse(value), cid };
}

0 comments on commit a5a62cf

Please sign in to comment.