Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Appview v1 handling clearly bad cursors #2088

Merged
merged 2 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/bsky/src/api/app/bsky/actor/getSuggestions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const skeleton = async (
): Promise<SkeletonState> => {
const { db } = ctx
const { viewer } = params
const alreadyIncluded = parseCursor(params.cursor)
const alreadyIncluded = parseCursor(params.cursor) // @NOTE handles bad cursor e.g. on appview swap
const { ref } = db.db.dynamic
const suggestions = await db.db
.selectFrom('suggested_follow')
Expand Down
1 change: 1 addition & 0 deletions packages/bsky/src/api/app/bsky/actor/searchActors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default function (server: Server, ctx: AppContext) {
let results: string[]
let resCursor: string | undefined
if (ctx.searchAgent) {
// @NOTE cursors wont change on appview swap
const res =
await ctx.searchAgent.api.app.bsky.unspecced.searchActorsSkeleton({
q: query,
Expand Down
6 changes: 6 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getActorFeeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ auth, params }) => {
const { actor, limit, cursor } = params
const viewer = auth.credentials.iss
if (TimeCidKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { feeds: [] },
}
}

const db = ctx.db.getReplica()
const actorService = ctx.services.actor(db)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getActorLikes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ const skeleton = async (
throw new InvalidRequestError('Profile not found')
}

if (FeedKeyset.clearlyBad(cursor)) {
return { params, feedItems: [] }
}

let feedItemsQb = feedService
.selectFeedItemQb()
.innerJoin('like', 'like.subject', 'feed_item.uri')
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getAuthorFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export const skeleton = async (
}
}

if (FeedKeyset.clearlyBad(cursor)) {
return { params, feedItems: [] }
}

// defaults to posts, reposts, and replies
let feedItemsQb = feedService
.selectFeedItemQb()
Expand Down
1 change: 1 addition & 0 deletions packages/bsky/src/api/app/bsky/feed/getFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default function (server: Server, ctx: AppContext) {
authorization: req.headers['authorization'],
'accept-language': req.headers['accept-language'],
})
// @NOTE feed cursors should not be affected by appview swap
const { timerSkele, timerHydr, resHeaders, ...result } = await getFeed(
{ ...params, viewer },
{
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getLikes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const skeleton = async (
const { uri, cid, limit, cursor } = params
const { ref } = db.db.dynamic

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, likes: [] }
}

let builder = db.db
.selectFrom('like')
.where('like.subject', '=', uri)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getListFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ export const skeleton = async (
const { db } = ctx
const { ref } = db.db.dynamic

if (FeedKeyset.clearlyBad(cursor)) {
return { params, feedItems: [] }
}

const keyset = new FeedKeyset(ref('post.sortAt'), ref('post.cid'))
const sortFrom = keyset.unpack(cursor)?.primary

Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getRepostedBy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ const skeleton = async (
const { limit, cursor, uri, cid } = params
const { ref } = db.db.dynamic

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, repostedBy: [] }
}

let builder = db.db
.selectFrom('repost')
.where('repost.subject', '=', uri)
Expand Down
2 changes: 1 addition & 1 deletion packages/bsky/src/api/app/bsky/feed/getSuggestedFeeds.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export default function (server: Server, ctx: AppContext) {
server.app.bsky.feed.getSuggestedFeeds({
auth: ctx.authVerifier.standardOptional,
handler: async ({ auth }) => {
// @NOTE ignores cursor, doesn't matter for appview swap
const viewer = auth.credentials.iss

const db = ctx.db.getReplica()
const feedService = ctx.services.feed(db)
const actorService = ctx.services.actor(db)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/feed/getTimeline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ export const skeleton = async (
return skeletonLimit1(params, ctx)
}

if (FeedKeyset.clearlyBad(cursor)) {
return { params, feedItems: [] }
}

const keyset = new FeedKeyset(ref('feed_item.sortAt'), ref('feed_item.cid'))
const sortFrom = keyset.unpack(cursor)?.primary

Expand Down
1 change: 1 addition & 0 deletions packages/bsky/src/api/app/bsky/feed/searchPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const skeleton = async (
params: Params,
ctx: Context,
): Promise<SkeletonState> => {
// @NOTE cursors wont change on appview swap
const res = await ctx.searchAgent.api.app.bsky.unspecced.searchPostsSkeleton({
q: params.q,
cursor: params.cursor,
Expand Down
7 changes: 7 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ params, auth }) => {
const { limit, cursor } = params
const requester = auth.credentials.iss
if (TimeCidKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { blocks: [] },
}
}

const db = ctx.db.getReplica()
const { ref } = db.db.dynamic

Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getFollowers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const skeleton = async (
throw new InvalidRequestError(`Actor not found: ${actor}`)
}

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, followers: [], subject }
}

let followersReq = db.db
.selectFrom('follow')
.where('follow.subjectDid', '=', subject.did)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getFollows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ const skeleton = async (
throw new InvalidRequestError(`Actor not found: ${actor}`)
}

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, follows: [], creator }
}

let followsReq = db.db
.selectFrom('follow')
.where('follow.creator', '=', creator.did)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ const skeleton = async (
throw new InvalidRequestError(`List not found: ${list}`)
}

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, list: listRes, listItems: [] }
}

let itemsReq = graphService
.getListItemsQb()
.where('list_item.listUri', '=', list)
Expand Down
4 changes: 4 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getListBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ const skeleton = async (
const { limit, cursor, viewer } = params
const { ref } = db.db.dynamic

if (TimeCidKeyset.clearlyBad(cursor)) {
return { params, listInfos: [] }
}

let listsReq = graphService
.getListsQb(viewer)
.whereExists(
Expand Down
7 changes: 7 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getListMutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ params, auth }) => {
const { limit, cursor } = params
const requester = auth.credentials.iss
if (TimeCidKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { lists: [] },
}
}

const db = ctx.db.getReplica()
const { ref } = db.db.dynamic

Expand Down
7 changes: 7 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getLists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ params, auth }) => {
const { actor, limit, cursor } = params
const requester = auth.credentials.iss
if (TimeCidKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { lists: [] },
}
}

const db = ctx.db.getReplica()
const { ref } = db.db.dynamic

Expand Down
7 changes: 7 additions & 0 deletions packages/bsky/src/api/app/bsky/graph/getMutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ params, auth }) => {
const { limit, cursor } = params
const requester = auth.credentials.iss
if (TimeCidKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { mutes: [] },
}
}

const db = ctx.db.getReplica()
const { ref } = db.db.dynamic

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ const skeleton = async (
if (params.seenAt) {
throw new InvalidRequestError('The seenAt parameter is unsupported')
}
if (NotifsKeyset.clearlyBad(cursor)) {
return { params, notifs: [] }
}
let notifBuilder = db.db
.selectFrom('notification as notif')
.where('notif.did', '=', viewer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,17 @@ export default function (server: Server, ctx: AppContext) {
handler: async ({ auth, params }) => {
const { limit, cursor, query } = params
const requester = auth.credentials.iss
if (LikeCountKeyset.clearlyBad(cursor)) {
return {
encoding: 'application/json',
body: { feeds: [] },
}
}

const db = ctx.db.getReplica()
const { ref } = db.db.dynamic
const feedService = ctx.services.feed(db)
const actorService = ctx.services.actor(db)

let inner = db.db
.selectFrom('feed_generator')
.select([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export default function (server: Server, ctx: AppContext) {
const feedService = ctx.services.feed(db)
const viewer = auth.credentials.iss

// @NOTE bad cursor during appview swap handled within skeleton()
const result = await skeleton({ ...params, viewer }, { db, feedService })

return {
Expand Down
3 changes: 3 additions & 0 deletions packages/bsky/src/db/pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ export abstract class GenericKeyset<R, LR extends LabeledResult> {
abstract labelResult(result: R): LR
abstract labeledResultToCursor(labeled: LR): Cursor
abstract cursorToLabeledResult(cursor: Cursor): LR
static clearlyBad(cursor?: string) {
return cursor !== undefined && !cursor.includes('::')
}
packFromResult(results: R | R[]): string | undefined {
const result = Array.isArray(results) ? results.at(-1) : results
if (!result) return
Expand Down
9 changes: 9 additions & 0 deletions packages/bsky/tests/views/notifications.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,13 @@ describe('notification views', () => {
),
)
})

it('fails open on clearly bad cursor.', async () => {
const { data: notifs } =
await agent.api.app.bsky.notification.listNotifications(
{ cursor: 'bad' },
{ headers: await network.serviceHeaders(alice) },
)
expect(notifs).toEqual({ notifications: [] })
})
})
8 changes: 8 additions & 0 deletions packages/bsky/tests/views/timeline.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,4 +298,12 @@ describe('timeline views', () => {
),
)
})

it('fails open on clearly bad cursor.', async () => {
const { data: timeline } = await agent.api.app.bsky.feed.getTimeline(
{ cursor: 'bad' },
{ headers: await network.serviceHeaders(alice) },
)
expect(timeline).toEqual({ feed: [] })
})
})
Loading