UBERF-7266: Fix workspace rate limit (#5812)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-06-14 11:50:20 +07:00 committed by GitHub
parent ce4070412f
commit dda0446a73
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 50 additions and 33 deletions

View File

@ -106,16 +106,19 @@ export function serveAccount (
// We need to clean workspace with creating === true, since server is restarted. // We need to clean workspace with creating === true, since server is restarted.
void cleanInProgressWorkspaces(db, productId) void cleanInProgressWorkspaces(db, productId)
worker = new UpgradeWorker(db, p, version, txes, migrateOperations, productId) const performUpgrade = (process.env.PERFORM_UPGRADE ?? 'true') === 'true'
await worker.upgradeAll(measureCtx, { if (performUpgrade) {
errorHandler: async (ws, err) => { worker = new UpgradeWorker(db, p, version, txes, migrateOperations, productId)
Analytics.handleError(err) await worker.upgradeAll(measureCtx, {
}, errorHandler: async (ws, err) => {
force: false, Analytics.handleError(err)
console: false, },
logs: 'upgrade-logs', force: false,
parallel: parseInt(process.env.PARALLEL ?? '1') console: false,
}) logs: 'upgrade-logs',
parallel: parseInt(process.env.PARALLEL ?? '1')
})
}
}) })
const extractToken = (header: IncomingHttpHeaders): string | undefined => { const extractToken = (header: IncomingHttpHeaders): string | undefined => {

View File

@ -886,7 +886,7 @@ async function generateWorkspaceRecord (
let searchPromise: Promise<Workspace> | undefined let searchPromise: Promise<Workspace> | undefined
const rateLimiter = new RateLimiter(3) const rateLimiter = new RateLimiter(parseInt(process.env.RATELIMIT ?? '10'))
/** /**
* @public * @public
@ -905,26 +905,26 @@ export async function createWorkspace (
notifyHandler?: (workspace: Workspace) => void, notifyHandler?: (workspace: Workspace) => void,
postInitHandler?: (workspace: Workspace, model: Tx[]) => Promise<void> postInitHandler?: (workspace: Workspace, model: Tx[]) => Promise<void>
): Promise<{ workspaceInfo: Workspace, err?: any, model?: Tx[] }> { ): Promise<{ workspaceInfo: Workspace, err?: any, model?: Tx[] }> {
// We need to search for duplicate workspaceUrl
await searchPromise
// Safe generate workspace record.
searchPromise = generateWorkspaceRecord(db, email, productId, version, workspaceName, workspace)
const workspaceInfo = await searchPromise
notifyHandler?.(workspaceInfo)
const wsColl = db.collection<Omit<Workspace, '_id'>>(WORKSPACE_COLLECTION)
async function updateInfo (ops: Partial<Workspace>): Promise<void> {
await wsColl.updateOne({ _id: workspaceInfo._id }, { $set: ops })
console.log('update', ops)
}
await updateInfo({ createProgress: 10 })
return await rateLimiter.exec(async () => { return await rateLimiter.exec(async () => {
// We need to search for duplicate workspaceUrl
await searchPromise
// Safe generate workspace record.
searchPromise = generateWorkspaceRecord(db, email, productId, version, workspaceName, workspace)
const workspaceInfo = await searchPromise
notifyHandler?.(workspaceInfo)
const wsColl = db.collection<Omit<Workspace, '_id'>>(WORKSPACE_COLLECTION)
async function updateInfo (ops: Partial<Workspace>): Promise<void> {
await wsColl.updateOne({ _id: workspaceInfo._id }, { $set: ops })
console.log('update', ops)
}
await updateInfo({ createProgress: 10 })
const childLogger = ctx.newChild('createWorkspace', { workspace: workspaceInfo.workspace }) const childLogger = ctx.newChild('createWorkspace', { workspace: workspaceInfo.workspace })
const ctxModellogger: ModelLogger = { const ctxModellogger: ModelLogger = {
log: (msg, data) => { log: (msg, data) => {
@ -959,7 +959,8 @@ export async function createWorkspace (
true, true,
async (value) => { async (value) => {
await updateInfo({ createProgress: 20 + Math.round((Math.min(value, 100) / 100) * 30) }) await updateInfo({ createProgress: 20 + Math.round((Math.min(value, 100) / 100) * 30) })
} },
true
) )
await updateInfo({ createProgress: 50 }) await updateInfo({ createProgress: 50 })
model = await upgradeModel( model = await upgradeModel(

View File

@ -20,6 +20,7 @@ import core, {
Client as CoreClient, Client as CoreClient,
Doc, Doc,
Domain, Domain,
DOMAIN_FULLTEXT_BLOB,
DOMAIN_MODEL, DOMAIN_MODEL,
DOMAIN_TRANSIENT, DOMAIN_TRANSIENT,
MeasureContext, MeasureContext,
@ -29,7 +30,8 @@ import core, {
SortingOrder, SortingOrder,
TxCollectionCUD, TxCollectionCUD,
WorkspaceId, WorkspaceId,
type Blob type Blob,
type DocIndexState
} from '@hcengineering/core' } from '@hcengineering/core'
import { BlobClient, connect } from '@hcengineering/server-tool' import { BlobClient, connect } from '@hcengineering/server-tool'
import { createGzip } from 'node:zlib' import { createGzip } from 'node:zlib'
@ -223,7 +225,8 @@ export async function cloneWorkspace (
sourceWorkspaceId: WorkspaceId, sourceWorkspaceId: WorkspaceId,
targetWorkspaceId: WorkspaceId, targetWorkspaceId: WorkspaceId,
clearTime: boolean = true, clearTime: boolean = true,
progress: (value: number) => Promise<void> progress: (value: number) => Promise<void>,
skipFullText: boolean
): Promise<void> { ): Promise<void> {
const sourceConnection = (await connect(transactorUrl, sourceWorkspaceId, undefined, { const sourceConnection = (await connect(transactorUrl, sourceWorkspaceId, undefined, {
mode: 'backup' mode: 'backup'
@ -245,6 +248,10 @@ export async function cloneWorkspace (
let i = 0 let i = 0
for (const c of domains) { for (const c of domains) {
if (skipFullText && c === DOMAIN_FULLTEXT_BLOB) {
console.log('clone skip domain...', c)
continue
}
console.log('clone domain...', c) console.log('clone domain...', c)
// We need to clean target connection before copying something. // We need to clean target connection before copying something.
@ -321,6 +328,12 @@ export async function cloneWorkspace (
} catch (err: any) { } catch (err: any) {
console.log(err) console.log(err)
} }
// if full text is skipped, we need to clean stages for indexes.
if (p._class === core.class.DocIndexState && skipFullText) {
;(p as DocIndexState).stages = {}
}
if (collectionCud) { if (collectionCud) {
return { return {
...p, ...p,