[web] fetch project members in a single db query (#25662)

* [web] fetch project members in a single db query

GitOrigin-RevId: ca749327d4783c67a3ad81f611cd7d3e7fa84028
This commit is contained in:
Jakob Ackermann
2025-05-16 09:04:09 +01:00
committed by Copybot
parent 14cbd44d9b
commit e3e8d944b2
2 changed files with 41 additions and 54 deletions

View File

@@ -385,34 +385,32 @@ function _getMemberIdsWithPrivilegeLevelsFromFields(
}
async function _loadMembers(members) {
const limit = pLimit(3)
const results = await Promise.all(
members.map(member =>
limit(async () => {
const user = await UserGetter.promises.getUser(member.id, {
_id: 1,
email: 1,
features: 1,
first_name: 1,
last_name: 1,
signUpDate: 1,
})
if (user != null) {
const record = {
user,
privilegeLevel: member.privilegeLevel,
}
if (member.pendingEditor) {
record.pendingEditor = true
} else if (member.pendingReviewer) {
record.pendingReviewer = true
}
return record
} else {
return null
}
})
)
)
return results.filter(r => r != null)
const userIds = Array.from(new Set(members.map(m => m.id)))
const users = new Map()
for (const user of await UserGetter.promises.getUsers(userIds, {
_id: 1,
email: 1,
features: 1,
first_name: 1,
last_name: 1,
signUpDate: 1,
})) {
users.set(user._id.toString(), user)
}
return members
.map(member => {
const user = users.get(member.id)
if (!user) return null
const record = {
user,
privilegeLevel: member.privilegeLevel,
}
if (member.pendingEditor) {
record.pendingEditor = true
} else if (member.pendingReviewer) {
record.pendingReviewer = true
}
return record
})
.filter(r => r != null)
}

View File

@@ -52,6 +52,7 @@ describe('CollaboratorsGetter', function () {
this.UserGetter = {
promises: {
getUser: sinon.stub().resolves(null),
getUsers: sinon.stub().resolves([]),
},
}
this.ProjectMock = sinon.mock(Project)
@@ -205,21 +206,13 @@ describe('CollaboratorsGetter', function () {
describe('getInvitedMembersWithPrivilegeLevels', function () {
beforeEach(function () {
this.UserGetter.promises.getUser
.withArgs(this.readOnlyRef1.toString())
.resolves({ _id: this.readOnlyRef1 })
this.UserGetter.promises.getUser
.withArgs(this.readOnlyTokenRef.toString())
.resolves({ _id: this.readOnlyTokenRef })
this.UserGetter.promises.getUser
.withArgs(this.readWriteRef2.toString())
.resolves({ _id: this.readWriteRef2 })
this.UserGetter.promises.getUser
.withArgs(this.readWriteTokenRef.toString())
.resolves({ _id: this.readWriteTokenRef })
this.UserGetter.promises.getUser
.withArgs(this.reviewer1Ref.toString())
.resolves({ _id: this.reviewer1Ref })
this.UserGetter.promises.getUsers.resolves([
{ _id: this.readOnlyRef1 },
{ _id: this.readOnlyTokenRef },
{ _id: this.readWriteRef2 },
{ _id: this.readWriteTokenRef },
{ _id: this.reviewer1Ref },
])
})
it('should return an array of invited members with their privilege levels', async function () {
@@ -416,15 +409,11 @@ describe('CollaboratorsGetter', function () {
{ _id: this.reviewUser._id, email: this.reviewUser.email },
],
}
this.UserGetter.promises.getUser
.withArgs(this.owningUser._id.toString())
.resolves(this.owningUser)
this.UserGetter.promises.getUser
.withArgs(this.readWriteUser._id.toString())
.resolves(this.readWriteUser)
this.UserGetter.promises.getUser
.withArgs(this.reviewUser._id.toString())
.resolves(this.reviewUser)
this.UserGetter.promises.getUsers.resolves([
this.owningUser,
this.readWriteUser,
this.reviewUser,
])
this.ProjectEditorHandler.buildOwnerAndMembersViews.returns(this.views)
this.result =
await this.CollaboratorsGetter.promises.getAllInvitedMembers(