fix(connections): apply the block filter to GET and paginate the list - #388
Merged
singh-odyssey merged 1 commit intoAug 19, 2026
Conversation
|
Thanks for opening this PR, @MOHITKOURAV01! 👋 Our maintainers will review it shortly. Estimate Time is 5-8 hrs .Meanwhile please:
If anything changes, feel free to push updates—this thread will stay open. |
Blocking is only half-applied on this endpoint. POST guards `send` and `accept` with isBlockedBetween(), but GET never consulted src/lib/blocking.ts at all, so after a block: - the blocked user stayed in the caller's connections list with their name, photo, bio and location - a pending request from someone the caller blocked still sat in their incoming list, and accepting it 403s, which just looks broken - the person who blocked the caller was still listed too, since blocking is symmetric here The sidebar hid the thread (/api/conversations already filters with getBlockedUserIds) while the connections page kept rendering the person. Same helper, resolved once, applied to all three lists. For the accepted list the filter has to sit inside each OR branch, because the counterpart is the receiver when the caller sent the request and the sender when they received it. The handler also ran three unbounded findMany calls serially, each with included user records, even though none depends on the others. They now run in one Promise.all, the two pending lists are bounded at 100, and the accepted list is cursor-paginated with the shared src/lib/pagination.ts helpers. Its ordering gains an id tiebreaker — `updatedAt` alone is not stable, so two rows accepted in the same transaction could swap places between requests and make the cursor skip or repeat a row. The incoming/outgoing/connections response keys are unchanged, so ChatInterface and DashboardMatches keep working; `pagination` is additive. Closes TravellersMeet#383
MOHITKOURAV01
force-pushed
the
fix/383-connections-block-filter
branch
from
August 10, 2026 14:48
c67b172 to
d9bada5
Compare
Contributor
Author
On the red
|
singh-odyssey
approved these changes
Aug 11, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #383
The problem
Blocking is only half-applied on this endpoint.
POSTdoes the right thing —isBlockedBetween()guards bothsendandaccept.GETnever consultedsrc/lib/blocking.tsat all.So after A blocks B:
GET /api/conversationscorrectly drops the threadGET /api/connectionsstill returns B underconnections, with name, photo, bio and locationincominglist, and accepting it 403s — which just looks brokenThe sidebar hides the person while the connections page keeps rendering them, which defeats the point of the feature and is confusing on both sides.
The same handler also ran three unbounded
findManycalls serially, each withincluded user records, on every dashboard load.What this changes
Block filter.
getBlockedUserIds()resolved once, applied to all three lists. For the accepted list the filter has to sit inside eachORbranch, because the counterpart is the receiver when the caller sent the request and the sender when they received it:Concurrency. The three queries don't depend on each other, so they run in one
Promise.allinstead of eachawaitblocking the next.Bounds. The two pending lists cap at 100. The accepted list is cursor-paginated with the shared
src/lib/pagination.tshelpers.Stable ordering.
orderBy: { updatedAt: "desc" }alone is not a stable sort — two rows accepted in the same transaction can swap places between requests, which would make the new cursor skip or repeat a row. Adds anidtiebreaker, matching what/api/messagesand/api/routesdo.Backwards compatibility
incoming,outgoingandconnectionskeep their shapes and their keys, soChatInterfaceandDashboardMatchesneed no changes.paginationis additive — a follow-up can wire a "load more" onto it.Tests
The existing file was for
GET(2 cases) andPOST(4 cases). ThePOSTcases are unchanged; the twoGETcases now pass a realNextRequest, since the handler readssearchParams. 14 newGETcases on top.Worth noting: the block tests drive
prisma.block.findManyrather than stubbinggetBlockedUserIds, so the real symmetry logic stays under test —blockedWith()alternates the direction of eachBlockrow on purpose.The concurrency test holds the first query's promise open and asserts all three have started, which fails against the serial version.
Verification
npx vitest run src/app/api/connections— 20 passed (4 pre-existing POST cases + 16)main's baseline: 9 failing files / 23 failing tests before and afternpx tsc --noEmitreports nothing new for this pathNote on the base branch
maindoes not currently typecheck (#366, fixed by #379). Nothing here touches those files.