Skip to content

Commit

Permalink
feat: GetMutualFriends also retrieves profiles and improves the response
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinszuchet committed Jan 22, 2025
1 parent 77fbe7e commit 2ab5fcd
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 49 deletions.
2 changes: 1 addition & 1 deletion src/adapters/rpc-server/rpc-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function createRpcServerComponent({
const rpcServerPort = (await config.getNumber('RPC_SERVER_PORT')) || 8085

const getFriends = await getFriendsService({ components: { logs, db, catalystClient, config } })
const getMutualFriends = getMutualFriendsService({ components: { logs, db } })
const getMutualFriends = await getMutualFriendsService({ components: { logs, db, catalystClient, config } })
const getPendingFriendshipRequests = getPendingFriendshipRequestsService({ components: { logs, db } })
const getSentFriendshipRequests = getSentFriendshipRequestsService({ components: { logs, db } })
const upsertFriendship = upsertFriendshipService({ components: { logs, db, pubsub } })
Expand Down
15 changes: 12 additions & 3 deletions src/adapters/rpc-server/services/get-mutual-friends.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,31 @@ import {
} from '@dcl/protocol/out-js/decentraland/social_service/v2/social_service_v2.gen'
import { normalizeAddress } from '../../../utils/address'
import { getPage } from '../../../utils/pagination'
import { parseProfilesToFriends } from '../../../logic/friends'

export function getMutualFriendsService({ components: { logs, db } }: RPCServiceContext<'logs' | 'db'>) {
export async function getMutualFriendsService({
components: { logs, db, catalystClient, config }
}: RPCServiceContext<'logs' | 'db' | 'catalystClient' | 'config'>) {
const logger = logs.getLogger('get-mutual-friends-service')
const contentServerUrl = await config.requireString('CONTENT_SERVER_URL')

return async function (request: GetMutualFriendsPayload, context: RpcServerContext): Promise<PaginatedUsersResponse> {
logger.debug(`getting mutual friends ${context.address}<>${request.user!.address}`)
logger.debug(`Getting mutual friends ${context.address}<>${request.user!.address}`)

try {
const { address: requester } = context
const { pagination, user } = request
const requested = normalizeAddress(user!.address)

const [mutualFriends, total] = await Promise.all([
db.getMutualFriends(requester, requested, pagination),
db.getMutualFriendsCount(requester, requested)
])

const profiles = await catalystClient.getEntitiesByPointers(mutualFriends.map((friend) => friend.address))

return {
users: mutualFriends,
users: parseProfilesToFriends(profiles, contentServerUrl),
paginationData: {
total,
page: getPage(pagination?.limit || FRIENDSHIPS_PER_PAGE, pagination?.offset)
Expand Down
14 changes: 14 additions & 0 deletions test/mocks/friend.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Friend } from '../../src/types'

export const createMockFriend = (address: string): Friend => ({
address
})

export function parseExpectedFriends(contentServerUrl: string) {
return (address: string) => ({
address,
name: `Profile name ${address}`,
hasClaimedName: true,
profilePictureUrl: `${contentServerUrl}/contents/bafybeiasdfqwer`
})
}
15 changes: 3 additions & 12 deletions test/unit/adapters/rpc-server/services/get-friends.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { mockCatalystClient, mockConfig, mockDb, mockLogs } from '../../../../mocks/components'
import { getFriendsService } from '../../../../../src/adapters/rpc-server/services/get-friends'
import { RpcServerContext, Friend } from '../../../../../src/types'
import { RpcServerContext } from '../../../../../src/types'
import { createMockProfile } from '../../../../mocks/profile'
import { createMockFriend, parseExpectedFriends } from '../../../../mocks/friend'

describe('getFriendsService', () => {
let getFriends: Awaited<ReturnType<typeof getFriendsService>>
Expand Down Expand Up @@ -34,12 +35,7 @@ describe('getFriendsService', () => {
const response = await getFriends({ pagination: { limit: 10, offset: 0 } }, rpcContext)

expect(response).toEqual({
users: addresses.map((address) => ({
address,
name: `Profile name ${address}`,
hasClaimedName: true,
profilePictureUrl: `${contentServerUrl}/contents/bafybeiasdfqwer`
})),
users: addresses.map(parseExpectedFriends(contentServerUrl)),
paginationData: {
total: totalFriends,
page: 1
Expand Down Expand Up @@ -93,9 +89,4 @@ describe('getFriendsService', () => {
}
})
})

// Helper to create a mock friendship object
const createMockFriend = (address): Friend => ({
address
})
})
68 changes: 35 additions & 33 deletions test/unit/adapters/rpc-server/services/get-mutual-friends.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { mockDb, mockLogs } from '../../../../mocks/components'
import { mockCatalystClient, mockConfig, mockDb, mockLogs } from '../../../../mocks/components'
import { getMutualFriendsService } from '../../../../../src/adapters/rpc-server/services/get-mutual-friends'
import { FRIENDSHIPS_PER_PAGE } from '../../../../../src/adapters/rpc-server/constants'
import { GetMutualFriendsPayload } from '@dcl/protocol/out-js/decentraland/social_service/v2/social_service_v2.gen'
import { RpcServerContext, AppComponents } from '../../../../../src/types'
import { RpcServerContext } from '../../../../../src/types'
import { createMockProfile } from '../../../../mocks/profile'
import { createMockFriend, parseExpectedFriends } from '../../../../mocks/friend'

describe('getMutualFriendsService', () => {
let components: jest.Mocked<Pick<AppComponents, 'db' | 'logs'>>
let getMutualFriends: ReturnType<typeof getMutualFriendsService>
let getMutualFriends: Awaited<ReturnType<typeof getMutualFriendsService>>

const contentServerUrl = 'https://peer.decentraland.org/content'

const rpcContext: RpcServerContext = {
address: '0x123',
Expand All @@ -18,50 +20,34 @@ describe('getMutualFriendsService', () => {
pagination: { limit: 10, offset: 0 }
}

beforeEach(() => {
components = { db: mockDb, logs: mockLogs }
getMutualFriends = getMutualFriendsService({ components })
beforeEach(async () => {
mockConfig.requireString.mockResolvedValueOnce(contentServerUrl)
getMutualFriends = await getMutualFriendsService({
components: { db: mockDb, logs: mockLogs, catalystClient: mockCatalystClient, config: mockConfig }
})
})

it('should return the correct list of mutual friends with pagination data', async () => {
const mockMutualFriends = [{ address: '0x789' }, { address: '0xabc' }]
const addresses = ['0x789', '0xabc']
const mockMutualFriends = addresses.map(createMockFriend)
const mockMutualFriendsProfiles = addresses.map(createMockProfile)
const totalMutualFriends = 2

mockDb.getMutualFriends.mockResolvedValueOnce(mockMutualFriends)
mockDb.getMutualFriendsCount.mockResolvedValueOnce(totalMutualFriends)
mockCatalystClient.getEntitiesByPointers.mockResolvedValueOnce(mockMutualFriendsProfiles)

const response = await getMutualFriends(mutualFriendsRequest, rpcContext)

expect(response).toEqual({
users: mockMutualFriends,
users: addresses.map(parseExpectedFriends(contentServerUrl)),
paginationData: {
total: totalMutualFriends,
page: 1 // First page is 1
page: 1
}
})
})

it('should respect the pagination limit', async () => {
const mockMutualFriends = Array.from({ length: FRIENDSHIPS_PER_PAGE }, (_, i) => ({
address: `0x${i + 1}`
}))
const totalMutualFriends = FRIENDSHIPS_PER_PAGE + 5

mockDb.getMutualFriends.mockResolvedValueOnce(mockMutualFriends)
mockDb.getMutualFriendsCount.mockResolvedValueOnce(totalMutualFriends)

const response = await getMutualFriends(
{ ...mutualFriendsRequest, pagination: { limit: FRIENDSHIPS_PER_PAGE, offset: 0 } },
rpcContext
)

expect(response.users).toHaveLength(FRIENDSHIPS_PER_PAGE)
expect(response.paginationData).toEqual({
total: totalMutualFriends,
page: 1 // First page is 1
})
})

it('should return an empty list if no mutual friends are found', async () => {
mockDb.getMutualFriends.mockResolvedValueOnce([])
mockDb.getMutualFriendsCount.mockResolvedValueOnce(0)
Expand All @@ -75,7 +61,7 @@ describe('getMutualFriendsService', () => {
users: [],
paginationData: {
total: 0,
page: 1 // First page is 1, even when no results
page: 1
}
})
})
Expand All @@ -95,4 +81,20 @@ describe('getMutualFriendsService', () => {
}
})
})

it('should handle errors from the catalyst gracefully', async () => {
mockCatalystClient.getEntitiesByPointers.mockImplementationOnce(() => {
throw new Error('Catalyst error')
})

const response = await getMutualFriends(mutualFriendsRequest, rpcContext)

expect(response).toEqual({
users: [],
paginationData: {
total: 0,
page: 1
}
})
})
})

0 comments on commit 2ab5fcd

Please sign in to comment.