mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-11 12:17:44 +02:00
UBERF-6202: Use only one mongo pull per configuration (#5073)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -44,9 +44,8 @@ import {
|
||||
DummyFullTextAdapter,
|
||||
type FullTextAdapter
|
||||
} from '@hcengineering/server-core'
|
||||
import { type MongoClient } from 'mongodb'
|
||||
import { createMongoAdapter, createMongoTxAdapter } from '..'
|
||||
import { getMongoClient, shutdown } from '../utils'
|
||||
import { getMongoClient, type MongoClientReference, shutdown } from '../utils'
|
||||
import { genMinModel } from './minmodel'
|
||||
import { createTaskModel, type Task, type TaskComment, taskPlugin } from './tasks'
|
||||
|
||||
@@ -80,7 +79,7 @@ async function createNullContentTextAdapter (): Promise<ContentTextAdapter> {
|
||||
|
||||
describe('mongo operations', () => {
|
||||
const mongodbUri: string = process.env.MONGO_URL ?? 'mongodb://localhost:27017'
|
||||
let mongoClient!: MongoClient
|
||||
let mongoClient!: MongoClientReference
|
||||
let dbId: string = generateId()
|
||||
let hierarchy: Hierarchy
|
||||
let model: ModelDb
|
||||
@@ -88,7 +87,7 @@ describe('mongo operations', () => {
|
||||
let operations: TxOperations
|
||||
|
||||
beforeAll(async () => {
|
||||
mongoClient = await getMongoClient(mongodbUri)
|
||||
mongoClient = getMongoClient(mongodbUri)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
@@ -101,7 +100,7 @@ describe('mongo operations', () => {
|
||||
|
||||
afterEach(async () => {
|
||||
try {
|
||||
await mongoClient.db(dbId).dropDatabase()
|
||||
await (await mongoClient.getClient()).db(dbId).dropDatabase()
|
||||
} catch (eee) {}
|
||||
})
|
||||
|
||||
|
||||
@@ -67,11 +67,10 @@ import {
|
||||
type Db,
|
||||
type Document,
|
||||
type Filter,
|
||||
type MongoClient,
|
||||
type Sort,
|
||||
type UpdateFilter
|
||||
} from 'mongodb'
|
||||
import { getMongoClient, getWorkspaceDB } from './utils'
|
||||
import { getMongoClient, getWorkspaceDB, type MongoClientReference } from './utils'
|
||||
|
||||
function translateDoc (doc: Doc): Document {
|
||||
return { ...doc, '%hash%': null }
|
||||
@@ -106,7 +105,7 @@ abstract class MongoAdapterBase implements DbAdapter {
|
||||
protected readonly db: Db,
|
||||
protected readonly hierarchy: Hierarchy,
|
||||
protected readonly modelDb: ModelDb,
|
||||
protected readonly client: MongoClient
|
||||
protected readonly client: MongoClientReference
|
||||
) {}
|
||||
|
||||
async init (): Promise<void> {}
|
||||
@@ -1408,8 +1407,8 @@ export async function createMongoAdapter (
|
||||
workspaceId: WorkspaceId,
|
||||
modelDb: ModelDb
|
||||
): Promise<DbAdapter> {
|
||||
const client = await getMongoClient(url)
|
||||
const db = getWorkspaceDB(client, workspaceId)
|
||||
const client = getMongoClient(url)
|
||||
const db = getWorkspaceDB(await client.getClient(), workspaceId)
|
||||
|
||||
return new MongoAdapter(db, hierarchy, modelDb, client)
|
||||
}
|
||||
@@ -1423,7 +1422,7 @@ export async function createMongoTxAdapter (
|
||||
workspaceId: WorkspaceId,
|
||||
modelDb: ModelDb
|
||||
): Promise<TxAdapter> {
|
||||
const client = await getMongoClient(url)
|
||||
const db = getWorkspaceDB(client, workspaceId)
|
||||
const client = getMongoClient(url)
|
||||
const db = getWorkspaceDB(await client.getClient(), workspaceId)
|
||||
return new MongoTxAdapter(db, hierarchy, modelDb, client)
|
||||
}
|
||||
|
||||
+54
-12
@@ -16,7 +16,7 @@
|
||||
import { toWorkspaceString, type WorkspaceId } from '@hcengineering/core'
|
||||
import { type Db, MongoClient, type MongoClientOptions } from 'mongodb'
|
||||
|
||||
let connections: MongoClient[] = []
|
||||
const connections = new Map<string, MongoClientReference>()
|
||||
|
||||
// Register mongo close on process exit.
|
||||
process.on('exit', () => {
|
||||
@@ -30,24 +30,66 @@ process.on('exit', () => {
|
||||
*/
|
||||
export async function shutdown (): Promise<void> {
|
||||
for (const c of connections.values()) {
|
||||
await c.close()
|
||||
await c.close(true)
|
||||
}
|
||||
connections = []
|
||||
connections.clear()
|
||||
}
|
||||
|
||||
export class MongoClientReference {
|
||||
count: number
|
||||
client: MongoClient | Promise<MongoClient>
|
||||
|
||||
constructor (client: MongoClient | Promise<MongoClient>) {
|
||||
this.count = 1
|
||||
this.client = client
|
||||
}
|
||||
|
||||
async getClient (): Promise<MongoClient> {
|
||||
if (this.client instanceof Promise) {
|
||||
this.client = await this.client
|
||||
}
|
||||
return this.client
|
||||
}
|
||||
|
||||
async close (force: boolean = false): Promise<void> {
|
||||
this.count--
|
||||
if (this.count === 0 || force) {
|
||||
if (force) {
|
||||
this.count = 0
|
||||
}
|
||||
await (await this.client).close()
|
||||
}
|
||||
}
|
||||
|
||||
addRef (): void {
|
||||
this.count++
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a workspace connection to DB
|
||||
* @public
|
||||
*/
|
||||
export async function getMongoClient (uri: string, options?: MongoClientOptions): Promise<MongoClient> {
|
||||
export function getMongoClient (uri: string, options?: MongoClientOptions): MongoClientReference {
|
||||
const extraOptions = JSON.parse(process.env.MONGO_OPTIONS ?? '{}')
|
||||
const client = await MongoClient.connect(uri, {
|
||||
...options,
|
||||
enableUtf8Validation: false,
|
||||
maxConnecting: 1024,
|
||||
...extraOptions
|
||||
})
|
||||
connections.push(client)
|
||||
return client
|
||||
const key = `${uri}${process.env.MONGO_OPTIONS}`
|
||||
let existing = connections.get(key)
|
||||
|
||||
// If not created or closed
|
||||
if (existing === undefined || existing.count === 0) {
|
||||
existing = new MongoClientReference(
|
||||
MongoClient.connect(uri, {
|
||||
...options,
|
||||
enableUtf8Validation: false,
|
||||
maxConnecting: 1024,
|
||||
...extraOptions
|
||||
})
|
||||
)
|
||||
connections.set(key, existing)
|
||||
} else {
|
||||
existing.addRef()
|
||||
}
|
||||
return existing
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user