perf: db metrix

This commit is contained in:
Mir Arif Hasan
2023-09-15 12:54:58 +06:00
parent 1431ecc6d7
commit dcbbd34247
11 changed files with 689 additions and 40 deletions

View File

@@ -21,7 +21,8 @@
"test:cov": "jest --coverage",
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
"test:e2e": "jest --config ./test/jest-e2e.json",
"do-test": "pnpm run test"
"do-test": "pnpm run test",
"seed": "node --loader ts-node/esm prisma/seed.ts"
},
"dependencies": {
"@nestjs-modules/mailer": "^1.8.1",
@@ -57,6 +58,7 @@
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"passport-microsoft": "^1.0.0",
"pg": "^8.11.3",
"prisma": "^4.16.2",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",

View File

@@ -0,0 +1,58 @@
import { PrismaClient, TeamMemberRole } from '@prisma/client';
const prisma = new PrismaClient();
const noOfUsers = 600000;
const getAllUser = async () => {
const users = await prisma.user.findMany();
return users;
};
const createUsers = async () => {
for (let i = 1; i <= noOfUsers; i++) {
try {
await prisma.user.create({
data: {
email: `${i}@gmail.com`,
},
});
} catch (_) {}
}
};
const createTeams = async () => {
const users = await getAllUser();
for (let i = 0; i < users.length; i++) {
try {
await prisma.team.create({
data: {
name: `Team ${i + 1}`,
members: {
create: {
userUid: users[i].uid,
role: TeamMemberRole.OWNER,
},
},
},
});
} catch (_) {}
}
};
async function main() {
console.log('Seeding...');
await createUsers();
await createTeams();
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (e) => {
console.error(e);
await prisma.$disconnect();
process.exit(1);
});

View File

@@ -20,6 +20,7 @@ import { ShortcodeModule } from './shortcode/shortcode.module';
import { COOKIES_NOT_FOUND } from './errors';
import { ThrottlerModule } from '@nestjs/throttler';
import { AppController } from './app.controller';
import { DbModule } from './db/db.module';
@Module({
imports: [
@@ -66,6 +67,7 @@ import { AppController } from './app.controller';
ttl: +process.env.RATE_LIMIT_TTL,
limit: +process.env.RATE_LIMIT_MAX,
}),
DbModule,
UserModule,
AuthModule,
AdminModule,

View File

@@ -0,0 +1 @@
export const PG_CONNECTION = 'PG_CONNECTION';

View File

@@ -0,0 +1,21 @@
import { Global, Module } from '@nestjs/common';
import { Pool } from 'pg';
import { PG_CONNECTION } from 'src/constants';
const dbProvider = {
provide: PG_CONNECTION,
useValue: new Pool({
user: 'postgres',
host: 'hoppscotch-db',
database: 'hoppscotch',
password: 'testpass',
port: 5432,
}),
};
@Global()
@Module({
providers: [dbProvider],
exports: [dbProvider],
})
export class DbModule {}

View File

@@ -7,7 +7,11 @@ export class PrismaService
implements OnModuleInit, OnModuleDestroy
{
constructor() {
super();
super(
{
log: ['query', 'info', 'warn', 'error'],
}
);
}
async onModuleInit() {
await this.$connect();

View File

@@ -22,6 +22,7 @@ import { throwErr } from 'src/utils';
import { AuthUser } from 'src/types/AuthUser';
import { GqlThrottlerGuard } from 'src/guards/gql-throttler.guard';
import { SkipThrottle } from '@nestjs/throttler';
import { cons } from 'fp-ts/lib/ReadonlyNonEmptyArray';
@UseGuards(GqlThrottlerGuard)
@Resolver(() => Team)
@@ -55,8 +56,13 @@ export class TeamResolver {
description: 'Returns the list of members of a team',
complexity: 10,
})
teamMembers(@Parent() team: Team): Promise<TeamMember[]> {
return this.teamService.getTeamMembers(team.id);
async teamMembers(@Parent() team: Team): Promise<TeamMember[]> {
const startR = Date.now();
const members = await this.teamService.getTeamMembers(team.id);
const endR = Date.now();
console.log('response generation: (teamMembers)', endR - startR, 'ms');
return members;
}
@ResolveField(() => TeamMemberRole, {
@@ -64,41 +70,61 @@ export class TeamResolver {
nullable: true,
})
@UseGuards(GqlAuthGuard)
myRole(
async myRole(
@Parent() team: Team,
@GqlUser() user: AuthUser,
): Promise<TeamMemberRole | null> {
return this.teamService.getRoleOfUserInTeam(team.id, user.uid);
const startR = Date.now();
const role = await this.teamService.getRoleOfUserInTeam(team.id, user.uid);
const endR = Date.now();
console.log('response generation: (myRole)', endR - startR, 'ms');
return role;
}
@ResolveField(() => Int, {
description: 'The number of users with the OWNER role in the team',
})
ownersCount(@Parent() team: Team): Promise<number> {
return this.teamService.getCountOfUsersWithRoleInTeam(
async ownersCount(@Parent() team: Team): Promise<number> {
const startR = Date.now();
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id,
TeamMemberRole.OWNER,
);
const endR = Date.now();
console.log('response generation: (ownersCount)', endR - startR, 'ms');
return count;
}
@ResolveField(() => Int, {
description: 'The number of users with the EDITOR role in the team',
})
editorsCount(@Parent() team: Team): Promise<number> {
return this.teamService.getCountOfUsersWithRoleInTeam(
async editorsCount(@Parent() team: Team): Promise<number> {
const startR = Date.now();
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id,
TeamMemberRole.EDITOR,
);
const endR = Date.now();
console.log('response generation: (editorsCount)', endR - startR, 'ms');
return count;
}
@ResolveField(() => Int, {
description: 'The number of users with the VIEWER role in the team',
})
viewersCount(@Parent() team: Team): Promise<number> {
return this.teamService.getCountOfUsersWithRoleInTeam(
async viewersCount(@Parent() team: Team): Promise<number> {
const startR = Date.now();
const count = await this.teamService.getCountOfUsersWithRoleInTeam(
team.id,
TeamMemberRole.VIEWER,
);
const endR = Date.now();
console.log('response generation: (viewersCount)', endR - startR, 'ms');
return count;
}
// Query
@@ -106,7 +132,7 @@ export class TeamResolver {
description: 'List of teams that the executing user belongs to.',
})
@UseGuards(GqlAuthGuard)
myTeams(
async myTeams(
@GqlUser() user: AuthUser,
@Args({
name: 'cursor',
@@ -117,7 +143,15 @@ export class TeamResolver {
})
cursor?: string,
): Promise<Team[]> {
return this.teamService.getTeamsOfUser(user.uid, cursor ?? null);
const startR = Date.now();
const teams = await this.teamService.getTeamsOfUser(
user.uid,
cursor ?? null,
);
const endR = Date.now();
console.log('response generation: (myTeams)', endR - startR, 'ms');
return teams;
}
@Query(() => Team, {
@@ -130,7 +164,7 @@ export class TeamResolver {
TeamMemberRole.EDITOR,
TeamMemberRole.OWNER,
)
team(
async team(
@Args({
name: 'teamID',
type: () => ID,
@@ -138,7 +172,12 @@ export class TeamResolver {
})
teamID: string,
): Promise<Team | null> {
return this.teamService.getTeamWithID(teamID);
const startR = Date.now();
const team = await this.teamService.getTeamWithID(teamID);
const endR = Date.now();
console.log('response generation: (team)', endR - startR, 'ms');
return team;
}
// Mutation
@@ -151,7 +190,11 @@ export class TeamResolver {
@Args({ name: 'name', description: 'Displayed name of the team' })
name: string,
): Promise<Team> {
const startR = Date.now();
const team = await this.teamService.createTeam(name, user.uid);
const endR = Date.now();
console.log('response generation: (createTeam)', endR - startR, 'ms');
if (E.isLeft(team)) throwErr(team.left);
return team.right;
}
@@ -169,7 +212,11 @@ export class TeamResolver {
})
teamID: string,
): Promise<boolean> {
const startR = Date.now();
const isUserLeft = await this.teamService.leaveTeam(teamID, user.uid);
const endR = Date.now();
console.log('response generation: (leaveTeam)', endR - startR, 'ms');
if (E.isLeft(isUserLeft)) throwErr(isUserLeft.left);
return isUserLeft.right;
}
@@ -194,7 +241,11 @@ export class TeamResolver {
})
userUid: string,
): Promise<boolean> {
const startR = Date.now();
const isRemoved = await this.teamService.leaveTeam(teamID, userUid);
const endR = Date.now();
console.log('response generation: (removeTeamMember)', endR - startR, 'ms');
if (E.isLeft(isRemoved)) throwErr(isRemoved.left);
return isRemoved.right;
}
@@ -210,7 +261,11 @@ export class TeamResolver {
@Args({ name: 'newName', description: 'The updated name of the team' })
newName: string,
): Promise<Team> {
const startR = Date.now();
const team = await this.teamService.renameTeam(teamID, newName);
const endR = Date.now();
console.log('response generation: (renameTeam)', endR - startR, 'ms');
if (E.isLeft(team)) throwErr(team.left);
return team.right;
}
@@ -224,7 +279,11 @@ export class TeamResolver {
@Args({ name: 'teamID', description: 'ID of the team', type: () => ID })
teamID: string,
): Promise<boolean> {
const startR = Date.now();
const isDeleted = await this.teamService.deleteTeam(teamID);
const endR = Date.now();
console.log('response generation: (deleteTeam)', endR - startR, 'ms');
if (E.isLeft(isDeleted)) throwErr(isDeleted.left);
return isDeleted.right;
}
@@ -254,11 +313,19 @@ export class TeamResolver {
})
newRole: TeamMemberRole,
): Promise<TeamMember> {
const startR = Date.now();
const teamMember = await this.teamService.updateTeamMemberRole(
teamID,
userUid,
newRole,
);
const endR = Date.now();
console.log(
'response generation: (updateTeamMemberRole)',
endR - startR,
'ms',
);
if (E.isLeft(teamMember)) throwErr(teamMember.left);
return teamMember.right;
}

View File

@@ -1,4 +1,4 @@
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import { TeamMember, TeamMemberRole, Team } from './team.model';
import { PrismaService } from '../prisma/prisma.service';
import { TeamMember as DbTeamMember } from '@prisma/client';
@@ -23,6 +23,8 @@ import * as T from 'fp-ts/Task';
import * as A from 'fp-ts/Array';
import { throwErr } from 'src/utils';
import { AuthUser } from '../types/AuthUser';
import { PG_CONNECTION } from 'src/constants';
import { Client } from 'pg';
@Injectable()
export class TeamService implements UserDataHandler, OnModuleInit {
@@ -30,8 +32,11 @@ export class TeamService implements UserDataHandler, OnModuleInit {
private readonly prisma: PrismaService,
private readonly userService: UserService,
private readonly pubsub: PubSubService,
@Inject(PG_CONNECTION) private conn: Client,
) {}
enableRawSql: boolean = false;
onModuleInit() {
this.userService.registerUserDataHandler(this);
}
@@ -52,12 +57,37 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string,
role: TeamMemberRole,
): Promise<number> {
return await this.prisma.teamMember.count({
if (this.enableRawSql) {
const startQ = Date.now();
const count = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${role}';`,
);
const endQ = Date.now();
console.log(
'getCountOfUsersWithRoleInTeam >>>>>>>>>>',
endQ - startQ,
'ms >>>>>',
count.rows,
);
return count.rows[0].count;
}
const startQ = Date.now();
const count = await this.prisma.teamMember.count({
where: {
teamID,
role,
},
});
const endQ = Date.now();
console.log(
'getCountOfUsersWithRoleInTeam >>>>>>>>>>',
endQ - startQ,
'ms >>>>>',
count,
);
return count;
}
async addMemberToTeamWithEmail(
@@ -77,6 +107,11 @@ export class TeamService implements UserDataHandler, OnModuleInit {
uid: string,
role: TeamMemberRole,
): Promise<TeamMember> {
const tm = await this.conn.query(
`INSERT INTO "TeamMember" (id, userUid, teamID, role) VALUES ('${new Date().toISOString()}', '${uid}', '${teamID}', '${role}') RETURNING *;`,
);
console.log('addMemberToTeam >>>>>>>>>>', tm.rows[0]);
const teamMember = await this.prisma.teamMember.create({
data: {
userUid: uid,
@@ -101,6 +136,31 @@ export class TeamService implements UserDataHandler, OnModuleInit {
}
async deleteTeam(teamID: string): Promise<E.Left<string> | E.Right<boolean>> {
if (this.enableRawSql) {
const startQ = Date.now();
const t = await this.conn.query(
`SELECT * FROM "Team" WHERE "id" = '${teamID}'`,
);
if (t.rows.length === 0) return E.left(TEAM_INVALID_ID);
await this.conn.query(
`DELETE FROM "TeamMember" WHERE "teamID" = '${teamID}' RETURNING *`,
);
await this.conn.query(`DELETE FROM "Team" WHERE "id" = '${teamID}'`);
const endQ = Date.now();
console.log(
'deleteTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
t.rows[0],
);
return E.right(true);
}
const startQ = Date.now();
const team = await this.prisma.team.findUnique({
where: {
id: teamID,
@@ -119,6 +179,8 @@ export class TeamService implements UserDataHandler, OnModuleInit {
id: teamID,
},
});
const endQ = Date.now();
console.log('deleteTeam >>>>>>>>>>', endQ - startQ, 'ms', '>>>>>', team);
return E.right(true);
}
@@ -135,6 +197,26 @@ export class TeamService implements UserDataHandler, OnModuleInit {
const isValidTitle = this.validateTeamName(newName);
if (E.isLeft(isValidTitle)) return isValidTitle;
if (this.enableRawSql) {
const startQ = Date.now();
const ut = await this.conn.query(
`UPDATE "Team" SET "name" = '${newName}' WHERE "id" = '${teamID}' RETURNING *`,
);
const endQ = Date.now();
console.log(
'renameTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
ut.rows[0],
);
return E.right(<Team>{
id: ut.rows[0].id,
name: ut.rows[0].name,
});
}
try {
const updatedTeam = await this.prisma.team.update({
where: {
@@ -156,6 +238,48 @@ export class TeamService implements UserDataHandler, OnModuleInit {
userUid: string,
newRole: TeamMemberRole,
): Promise<E.Left<string> | E.Right<TeamMember>> {
if (this.enableRawSql) {
const startQ = Date.now();
const oc = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${TeamMemberRole.OWNER}';`,
);
const tm = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
if (tm.rows.length === 0) return E.left(TEAM_MEMBER_NOT_FOUND);
const ownerCount = oc.rows[0].count;
if (
tm.rows[0].role === TeamMemberRole.OWNER &&
newRole != TeamMemberRole.OWNER &&
ownerCount === 1
) {
return E.left(TEAM_ONLY_ONE_OWNER);
}
const utm = await this.conn.query(
`UPDATE "teamMember" SET "role" = '${newRole}' WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
const endQ = Date.now();
console.log(
'updateTeamMemberRole >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
utm.rows[0],
);
const updatedMember: TeamMember = {
membershipID: utm.rows[0].id,
userUid: utm.rows[0].userUid,
role: TeamMemberRole[utm.rows[0].role],
};
this.pubsub.publish(`team/${teamID}/member_updated`, updatedMember);
return E.right(updatedMember);
}
const startQ = Date.now();
const ownerCount = await this.prisma.teamMember.count({
where: {
teamID,
@@ -192,6 +316,14 @@ export class TeamService implements UserDataHandler, OnModuleInit {
role: newRole,
},
});
const endQ = Date.now();
console.log(
'updateTeamMemberRole >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
result,
);
const updatedMember: TeamMember = {
membershipID: result.id,
@@ -208,6 +340,30 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string,
userUid: string,
): Promise<E.Left<string> | E.Right<boolean>> {
if (this.enableRawSql) {
const oc = await this.conn.query(
`SELECT COUNT(*) FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "role" = '${TeamMemberRole.OWNER}';`,
);
const ownerCount = oc.rows[0].count;
console.log('leaveTeam >>>>>>>>>>', oc.rows);
const member = await this.getTeamMember(teamID, userUid);
if (!member) return E.left(TEAM_INVALID_ID_OR_USER);
if (ownerCount === 1 && member.role === TeamMemberRole.OWNER) {
return E.left(TEAM_ONLY_ONE_OWNER);
}
const dtm = await this.conn.query(
`DELETE FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
console.log('leaveTeam >>>>>>>>>>', dtm);
this.pubsub.publish(`team/${teamID}/member_removed`, userUid);
return E.right(true);
}
const ownerCount = await this.prisma.teamMember.count({
where: {
teamID,
@@ -248,6 +404,34 @@ export class TeamService implements UserDataHandler, OnModuleInit {
const isValidName = this.validateTeamName(name);
if (E.isLeft(isValidName)) return isValidName;
if (this.enableRawSql) {
const startQ = Date.now();
const t = await this.conn.query(
`INSERT INTO "Team" (id, name) VALUES ('${new Date().toISOString()}', '${name}') RETURNING *`,
);
const tm = await this.conn.query(
`INSERT INTO "TeamMember" ("id", "userUid", "teamID", "role") VALUES ('${new Date().toISOString()}', '${creatorUid}' , '${
t.rows[0].id
}', '${TeamMemberRole.OWNER}') RETURNING *`,
);
const endQ = Date.now();
``;
console.log(
'createTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
t.rows[0],
tm.rows[0],
);
return E.right(<Team>{
id: t.rows[0].id,
name: t.rows[0].name,
});
}
const startQ = Date.now();
const team = await this.prisma.team.create({
data: {
name: name,
@@ -259,12 +443,42 @@ export class TeamService implements UserDataHandler, OnModuleInit {
},
},
});
const endQ = Date.now();
console.log('createTeam >>>>>>>>>> ', endQ - startQ, 'ms', '>>>>>', team);
return E.right(team);
}
async getTeamsOfUser(uid: string, cursor: string | null): Promise<Team[]> {
if (this.enableRawSql) {
const startQ = Date.now();
let users;
if (cursor) {
users = await this.conn.query(
`SELECT * FROM "TeamMember" LEFT JOIN "Team" ON "TeamMember"."teamID" = "Team"."id" WHERE "TeamMember"."userUid" = '${uid}' and "TeamMember"."teamID" > '${cursor}' LIMIT 10`,
);
} else {
users = await this.conn.query(
`SELECT * FROM "TeamMember" LEFT JOIN "Team" ON "TeamMember"."teamID" = "Team"."id" WHERE "TeamMember"."userUid" = '${uid}' LIMIT 10`,
);
}
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
users.rows,
);
return users.rows.map((entry) => ({
id: entry.teamID,
name: entry.name,
}));
}
if (!cursor) {
const startQ = Date.now();
const entries = await this.prisma.teamMember.findMany({
take: 10,
where: {
@@ -274,9 +488,18 @@ export class TeamService implements UserDataHandler, OnModuleInit {
team: true,
},
});
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
entries,
);
return entries.map((entry) => entry.team);
} else {
const startQ = Date.now();
const entries = await this.prisma.teamMember.findMany({
take: 10,
skip: 1,
@@ -293,17 +516,56 @@ export class TeamService implements UserDataHandler, OnModuleInit {
team: true,
},
});
const endQ = Date.now();
console.log(
'getTeamsOfUser >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
entries,
);
return entries.map((entry) => entry.team);
}
}
async getTeamWithID(teamID: string): Promise<Team | null> {
if (this.enableRawSql) {
const startQ = Date.now();
const team = await this.conn.query(
`SELECT * FROM "Team" WHERE "id" = '${teamID}'`,
);
const endQ = Date.now();
console.log(
'getTeamWithID >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
team.rows,
);
if (team.rows.length === 0) return null;
return <Team>{
id: team.rows[0].id,
name: team.rows[0].name,
};
}
try {
const startQ = Date.now();
const team = await this.prisma.team.findUnique({
where: {
id: teamID,
},
});
const endQ = Date.now();
console.log(
'getTeamWithID >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
team,
);
return team;
} catch (_e) {
@@ -353,7 +615,30 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string,
userUid: string,
): Promise<TeamMember | null> {
if (this.enableRawSql) {
const startQ = Date.now();
const member = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "userUid" = '${userUid}'`,
);
const endQ = Date.now();
console.log(
'getTeamMember >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
member.rows,
);
if (member.rows.length === 0) return null;
return <TeamMember>{
membershipID: member.rows[0].id,
userUid: member.rows[0].userUid,
role: TeamMemberRole[member.rows[0].role],
};
}
try {
const startQ = Date.now();
const teamMember = await this.prisma.teamMember.findUnique({
where: {
teamID_userUid: {
@@ -362,6 +647,14 @@ export class TeamService implements UserDataHandler, OnModuleInit {
},
},
});
const endQ = Date.now();
console.log(
'getTeamMember >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
teamMember,
);
if (!teamMember) return null;
@@ -433,11 +726,44 @@ export class TeamService implements UserDataHandler, OnModuleInit {
}
async getTeamMembers(teamID: string): Promise<TeamMember[]> {
if (this.enableRawSql) {
const startQ = Date.now();
const members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}'`,
);
const endQ = Date.now();
console.log(
'getTeamMembers >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
members.rows,
);
return members.rows.map((entry) => {
return {
membershipID: entry.id,
userUid: entry.userUid,
role: TeamMemberRole[entry.role],
};
});
}
const startQ = Date.now();
const dbTeamMembers = await this.prisma.teamMember.findMany({
where: {
teamID,
},
});
const endQ = Date.now();
console.log(
'getTeamMembers >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
dbTeamMembers,
);
const members = dbTeamMembers.map(
(entry) =>
@@ -470,8 +796,39 @@ export class TeamService implements UserDataHandler, OnModuleInit {
teamID: string,
cursor: string | null,
): Promise<TeamMember[]> {
if (this.enableRawSql) {
const startQ = Date.now();
let members;
if (cursor) {
members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' AND "id" > '${cursor}' LIMIT 10`,
);
}
members = await this.conn.query(
`SELECT * FROM "TeamMember" WHERE "teamID" = '${teamID}' LIMIT 10`,
);
const endQ = Date.now();
console.log(
'getMembersOfTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
members.rows,
);
return members.rows.map(
(entry) =>
<TeamMember>{
membershipID: entry.id,
userUid: entry.userUid,
role: TeamMemberRole[entry.role],
},
);
}
let teamMembers: DbTeamMember[];
const startQ = Date.now();
if (!cursor) {
teamMembers = await this.prisma.teamMember.findMany({
take: 10,
@@ -491,6 +848,14 @@ export class TeamService implements UserDataHandler, OnModuleInit {
},
});
}
const endQ = Date.now();
console.log(
'getMembersOfTeam >>>>>>>>>>',
endQ - startQ,
'ms',
'>>>>>',
teamMembers,
);
const members = teamMembers.map(
(entry) =>