UBERF-6523: Allow to use zstd (#5333)

Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2024-04-12 13:30:07 +07:00 committed by GitHub
parent ce7fc92e56
commit f8cc27b590
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 113 additions and 42 deletions

View File

@ -30,12 +30,8 @@
endpoint = endpoint.substring(0, endpoint.length - 1) endpoint = endpoint.substring(0, endpoint.length - 1)
} }
let data: any async function fetchStats (): Promise<void> {
let dataFront: any await fetch(endpoint + `/api/v1/statistics?token=${token}`, {})
let admin = false
onDestroy(
ticker.subscribe(() => {
void fetch(endpoint + `/api/v1/statistics?token=${token}`, {})
.then(async (json) => { .then(async (json) => {
data = await json.json() data = await json.json()
admin = data?.admin ?? false admin = data?.admin ?? false
@ -43,14 +39,25 @@
.catch((err) => { .catch((err) => {
console.error(err) console.error(err)
}) })
}
void fetch(`/api/v1/statistics?token=${token}`, {}) async function fetchUIStats (): Promise<void> {
await fetch(`/api/v1/statistics?token=${token}`, {})
.then(async (json) => { .then(async (json) => {
dataFront = await json.json() dataFront = await json.json()
}) })
.catch((err) => { .catch((err) => {
console.error(err) console.error(err)
}) })
}
let data: any
let dataFront: any
let admin = false
onDestroy(
ticker.subscribe(() => {
void fetchStats()
void fetchUIStats()
}) })
) )
const tabs: TabItem[] = [ const tabs: TabItem[] = [
@ -264,6 +271,24 @@
{/each} {/each}
</div> </div>
{:else if selectedTab === 'statistics'} {:else if selectedTab === 'statistics'}
{#if admin}
<div class="flex flex-col">
<div class="flex-row-center p-1">
<div class="p-3">1.</div>
<Button
icon={IconArrowRight}
label={getEmbeddedLabel('Wipe statistics')}
on:click={() => {
void fetch(endpoint + `/api/v1/manage?token=${token}&operation=wipe-statistics`, {
method: 'PUT'
}).then(async () => {
await fetchStats()
})
}}
/>
</div>
</div>
{/if}
<div class="flex-column p-3 h-full" style:overflow="auto"> <div class="flex-column p-3 h-full" style:overflow="auto">
{#if metricsData !== undefined} {#if metricsData !== undefined}
<MetricsInfo metrics={metricsData} /> <MetricsInfo metrics={metricsData} />

View File

@ -1,8 +1,9 @@
FROM node:20-alpine FROM node:20
WORKDIR /usr/src/app WORKDIR /usr/src/app
COPY bundle/bundle.js ./ COPY bundle/bundle.js ./
RUN npm install --ignore-scripts=false --verbose bufferutil utf-8-validate @mongodb-js/zstd --unsafe-perm
EXPOSE 3000 EXPOSE 3000
CMD [ "node", "bundle.js" ] CMD [ "node", "bundle.js" ]

View File

@ -1,8 +1,9 @@
FROM node:20-alpine FROM node:20
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN npm install --ignore-scripts=false --verbose bufferutil utf-8-validate @mongodb-js/zstd --unsafe-perm
COPY bundle/bundle.js ./ COPY bundle/bundle.js ./
EXPOSE 3000 EXPOSE 3000

View File

@ -2,7 +2,7 @@
FROM node:20 FROM node:20
WORKDIR /usr/src/app WORKDIR /usr/src/app
RUN npm install --ignore-scripts=false --verbose bufferutil --unsafe-perm RUN npm install --ignore-scripts=false --verbose bufferutil utf-8-validate @mongodb-js/zstd --unsafe-perm
COPY bundle/bundle.js ./ COPY bundle/bundle.js ./

View File

@ -1,13 +1,11 @@
FROM node:20-alpine FROM node:20
RUN apk add dumb-init
ENV NODE_ENV production ENV NODE_ENV production
WORKDIR /app WORKDIR /app
RUN npm install --ignore-scripts=false --verbose sharp@v0.32.6 --unsafe-perm RUN npm install --ignore-scripts=false --verbose sharp@v0.32.6 bufferutil utf-8-validate @mongodb-js/zstd --unsafe-perm
COPY bundle/bundle.js ./ COPY bundle/bundle.js ./
COPY dist/ ./dist/ COPY dist/ ./dist/
EXPOSE 8080 EXPOSE 8080
CMD [ "dumb-init", "node", "./bundle.js" ] CMD [ "node", "./bundle.js" ]

View File

@ -3,10 +3,9 @@ FROM node:20
ENV NODE_ENV production ENV NODE_ENV production
WORKDIR /app WORKDIR /app
RUN npm install --ignore-scripts=false --verbose bufferutil --unsafe-perm RUN npm install --ignore-scripts=false --verbose bufferutil utf-8-validate @mongodb-js/zstd --unsafe-perm
COPY bundle/bundle.js ./ COPY bundle/bundle.js ./
# COPY ./dist/*.node ./
EXPOSE 8080 EXPOSE 8080
CMD [ "node", "./bundle.js" ] CMD [ "node", "./bundle.js" ]

View File

@ -45,8 +45,7 @@ export function createRawMongoDBAdapter (url: string): RawDBAdapter {
const db = getWorkspaceDB(await client.getClient(), workspace) const db = getWorkspaceDB(await client.getClient(), workspace)
const coll = db.collection(domain) const coll = db.collection(domain)
let cursor = coll.find<T>(query as Filter<Document>, { let cursor = coll.find<T>(query as Filter<Document>, {
checkKeys: false, checkKeys: false
enableUtf8Validation: false
}) })
let total: number = -1 let total: number = -1

View File

@ -486,8 +486,7 @@ abstract class MongoAdapterBase implements DbAdapter {
if (options?.total === true) { if (options?.total === true) {
totalPipeline.push({ $count: 'total' }) totalPipeline.push({ $count: 'total' })
const totalCursor = this.db.collection(domain).aggregate(totalPipeline, { const totalCursor = this.db.collection(domain).aggregate(totalPipeline, {
checkKeys: false, checkKeys: false
enableUtf8Validation: false
}) })
const arr = await toArray(totalCursor) const arr = await toArray(totalCursor)
total = arr?.[0]?.total ?? 0 total = arr?.[0]?.total ?? 0
@ -592,8 +591,7 @@ abstract class MongoAdapterBase implements DbAdapter {
const mongoQuery = this.translateQuery(_class, query) const mongoQuery = this.translateQuery(_class, query)
let cursor = coll.find<T>(mongoQuery, { let cursor = coll.find<T>(mongoQuery, {
checkKeys: false, checkKeys: false
enableUtf8Validation: false
}) })
if (options?.projection !== undefined) { if (options?.projection !== undefined) {
@ -1252,15 +1250,19 @@ class MongoTxAdapter extends MongoAdapterBase implements TxAdapter {
} }
async getModel (ctx: MeasureContext): Promise<Tx[]> { async getModel (ctx: MeasureContext): Promise<Tx[]> {
const modelProjection = { const cursor = await ctx.with('find', {}, async () =>
this.db.collection<Tx>(DOMAIN_TX).find(
{ objectSpace: core.space.Model },
{
sort: {
_id: 1,
modifiedOn: 1
},
projection: {
'%hash%': 0 '%hash%': 0
} }
const cursor = await ctx.with('find', {}, async () => }
this.db )
.collection<Tx>(DOMAIN_TX)
.find({ objectSpace: core.space.Model })
.sort({ _id: 1, modifiedOn: 1 })
.project<Tx>(modelProjection)
) )
const model = await ctx.with('to-array', {}, async () => await toArray<Tx>(cursor)) const model = await ctx.with('to-array', {}, async () => await toArray<Tx>(cursor))
// We need to put all core.account.System transactions first // We need to put all core.account.System transactions first

View File

@ -22,7 +22,7 @@ import cors from 'cors'
import express from 'express' import express from 'express'
import http, { type IncomingMessage } from 'http' import http, { type IncomingMessage } from 'http'
import { WebSocketServer, type RawData, type WebSocket } from 'ws' import { WebSocketServer, type RawData, type WebSocket } from 'ws'
import { getStatistics } from './stats' import { getStatistics, wipeStatistics } from './stats'
import { import {
LOGGING_ENABLED, LOGGING_ENABLED,
type ConnectionSocket, type ConnectionSocket,
@ -118,7 +118,14 @@ export function startHttpServer (
res.writeHead(200) res.writeHead(200)
res.end() res.end()
break return
}
case 'wipe-statistics': {
wipeStatistics(ctx)
res.writeHead(200)
res.end()
return
} }
case 'reboot': { case 'reboot': {
process.exit(0) process.exit(0)

View File

@ -1,4 +1,10 @@
import { type MeasureContext, metricsAggregate } from '@hcengineering/core' import {
type MeasureContext,
MeasureMetricsContext,
type Metrics,
metricsAggregate,
type MetricsData
} from '@hcengineering/core'
import os from 'os' import os from 'os'
import { type SessionManager } from './types' import { type SessionManager } from './types'
@ -33,3 +39,36 @@ export function getStatistics (ctx: MeasureContext, sessions: SessionManager, ad
return data return data
} }
/**
* @public
*/
export function wipeStatistics (ctx: MeasureContext): void {
const toClean: (Metrics | MetricsData)[] = []
function cleanMetrics (m: Metrics | MetricsData): void {
m.operations = 0
m.value = 0
m.topResult = undefined
if ('measurements' in m) {
for (const v of Object.values(m.measurements)) {
toClean.push(v)
}
for (const v of Object.values(m.params)) {
for (const vv of Object.values(v)) {
toClean.push(vv)
}
}
}
}
if (ctx instanceof MeasureMetricsContext) {
toClean.push(ctx.metrics)
while (toClean.length > 0) {
const v = toClean.shift()
if (v === undefined) {
break
}
cleanMetrics(v)
}
}
}