UBERF-8083: Optimize account by email search (#6538)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-09-12 14:04:03 +07:00 committed by GitHub
parent 49113d8cd8
commit 04ce0d70ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 28 additions and 37 deletions

View File

@ -32,6 +32,7 @@ export abstract class MemDb extends TxProcessor implements Storage {
private readonly objectById = new Map<Ref<Doc>, Doc>()
private readonly accountByPersonId = new Map<Ref<Doc>, Account[]>()
private readonly accountByEmail = new Map<string, Account>()
constructor (protected readonly hierarchy: Hierarchy) {
super()
@ -81,6 +82,10 @@ export abstract class MemDb extends TxProcessor implements Storage {
return this.accountByPersonId.get(ref) ?? []
}
getAccountByEmail (email: Account['email']): Account | undefined {
return this.accountByEmail.get(email)
}
findObject<T extends Doc>(_id: Ref<T>): T | undefined {
const doc = this.objectById.get(_id)
return doc as T
@ -227,6 +232,7 @@ export abstract class MemDb extends TxProcessor implements Storage {
})
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
const account = doc as Account
this.accountByEmail.set(account.email, account)
if (account.person !== undefined) {
this.accountByPersonId.set(account.person, [...(this.accountByPersonId.get(account.person) ?? []), account])
}
@ -245,6 +251,7 @@ export abstract class MemDb extends TxProcessor implements Storage {
})
if (this.hierarchy.isDerived(doc._class, core.class.Account)) {
const account = doc as Account
this.accountByEmail.delete(account.email)
if (account.person !== undefined) {
const acc = this.accountByPersonId.get(account.person) ?? []
this.accountByPersonId.set(

View File

@ -23,7 +23,7 @@ async function connect (token: string): Promise<Client> {
}
async function getTxOperations (client: Client, token: Token, isDerived: boolean = false): Promise<TxOperations> {
const account = await client.findOne(core.class.Account, { email: token.email })
const account = client.getModel().getAccountByEmail(token.email)
const accountId = account?._id ?? core.account.System
return new TxOperations(client, accountId, isDerived)

View File

@ -140,7 +140,7 @@ export function getUser (modelDb: ModelDb, userEmail: string | undefined, admin?
if (userEmail === undefined) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
}
const account = modelDb.findAllSync(core.class.Account, { email: userEmail })[0]
const account = modelDb.getAccountByEmail(userEmail)
if (account === undefined) {
if (userEmail === systemAccountEmail || admin === true) {
return {
@ -181,7 +181,7 @@ export class SessionDataImpl implements SessionData {
}
getAccount (account: Ref<Account>): Account | undefined {
return this.modelDb.findAllSync(core.class.Account, { _id: account })[0]
return this.modelDb.findObject(account)
}
}

View File

@ -113,12 +113,10 @@ export class ClientSession implements Session {
}
async getAccount (ctx: ClientSessionCtx): Promise<void> {
const account = this._pipeline.context.modelDb.findAllSync(core.class.Account, { email: this.token.email })
if (account.length === 0 && this.token.extra?.admin === 'true') {
const systemAccount = this._pipeline.context.modelDb.findAllSync(core.class.Account, {
_id: this.token.email as Ref<Account>
})
if (systemAccount.length === 0) {
const account = this._pipeline.context.modelDb.getAccountByEmail(this.token.email)
if (account === undefined && this.token.extra?.admin === 'true') {
const systemAccount = this._pipeline.context.modelDb.findObject(this.token.email as Ref<Account>)
if (systemAccount === undefined) {
// Generate account for admin user
const factory = new TxFactory(core.account.System)
const email = `system:${this.token.email}`
@ -152,11 +150,11 @@ export class ClientSession implements Session {
await ctx.sendResponse(acc)
return
} else {
await ctx.sendResponse(systemAccount[0])
await ctx.sendResponse(systemAccount)
return
}
}
await ctx.sendResponse(account[0])
await ctx.sendResponse(account)
}
findAllRaw<T extends Doc>(

View File

@ -629,15 +629,7 @@ class TSessionManager implements SessionManager {
workspaceId: WorkspaceId
): Promise<void> {
try {
const user = (
await session.pipeline().context.modelDb.findAll(
core.class.Account,
{
email: session.getUser()
},
{ limit: 1 }
)
)[0]
const user = session.pipeline().context.modelDb.getAccountByEmail(session.getUser())
if (user === undefined) return
const clientCtx: ClientSessionCtx = {

View File

@ -16,6 +16,7 @@
import calendar, { Event, ExternalCalendar } from '@hcengineering/calendar'
import contact, { Channel, Contact, type Employee, type PersonAccount } from '@hcengineering/contact'
import core, {
TxOperations,
TxProcessor,
toIdMap,
type Account,
@ -25,17 +26,16 @@ import core, {
type Tx,
type TxCreateDoc,
type TxRemoveDoc,
type TxUpdateDoc,
TxOperations
type TxUpdateDoc
} from '@hcengineering/core'
import { generateToken } from '@hcengineering/server-token'
import setting, { Integration } from '@hcengineering/setting'
import { Collection, type Db } from 'mongodb'
import { CalendarClient } from './calendar'
import { CalendarController } from './calendarController'
import { getClient } from './client'
import config from './config'
import { SyncHistory, type ProjectCredentials, type User } from './types'
import { CalendarController } from './calendarController'
import { generateToken } from '@hcengineering/server-token'
export class WorkspaceClient {
private readonly txHandlers: ((...tx: Tx[]) => Promise<void>)[] = []
@ -109,9 +109,7 @@ export class WorkspaceClient {
}
async getUserId (email: string): Promise<Ref<Account>> {
const user = await this.client.findOne(core.class.Account, {
email
})
const user = this.client.getModel().getAccountByEmail(email)
if (user === undefined) {
throw new Error('User not found')
}

View File

@ -408,7 +408,7 @@ export class PlatformWorker {
}
// We need to re-bind previously created github:login account to a proper person.
const account = (await client.findOne(core.class.Account, { _id: payload.accountId })) as PersonAccount
const account = client.getModel().getObject(payload.accountId) as PersonAccount
const person = (await client.findOne(contact.class.Person, { _id: account.person })) as Person
if (person !== undefined) {
if (!revoke) {
@ -424,9 +424,7 @@ export class PlatformWorker {
})
}
const githubAccount = (await client.findOne(core.class.Account, {
email: 'github:' + update.login
})) as PersonAccount
const githubAccount = client.getModel().getAccountByEmail('github:' + update.login) as PersonAccount
if (githubAccount !== undefined && githubAccount.person !== account.person) {
const dummyPerson = githubAccount.person
// To add activity entry to dummy person.

View File

@ -19,14 +19,14 @@ import core, {
type AttachedDoc,
type Client,
type Doc,
MeasureContext,
type Ref,
type Tx,
type TxCollectionCUD,
type TxCreateDoc,
TxProcessor,
type TxRemoveDoc,
type TxUpdateDoc,
MeasureContext
type TxUpdateDoc
} from '@hcengineering/core'
import gmailP, { type NewMessage } from '@hcengineering/gmail'
import type { StorageAdapter } from '@hcengineering/server-core'
@ -92,9 +92,7 @@ export class WorkspaceClient {
}
async getUserId (email: string): Promise<Ref<Account>> {
const user = await this.client.findOne(core.class.Account, {
email
})
const user = this.client.getModel().getAccountByEmail(email)
if (user === undefined) {
throw new Error('User not found')
}

View File

@ -179,7 +179,7 @@ export class WorkspaceWorker {
// #region Users
async addUser ({ email, phone, conn }: TgUser): Promise<void> {
const user = (await this.client.findAll(core.class.Account, { email }, { limit: 1 }))[0]
const user = this.client.getModel().getAccountByEmail(email)
if (user === undefined) {
throw Error(`Unable to find user by email: ${email}`)