Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UBERF-6161: Storage configuration #5109

Merged
merged 1 commit into from
Apr 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
482 changes: 242 additions & 240 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions dev/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ services:
environment:
- SERVER_PORT=8080
- SERVER_SECRET=secret
- MONGO_URL=mongodb://mongodb:27017
- ACCOUNTS_URL=http://localhost:3000
- REKONI_URL=http://localhost:4004
- CALENDAR_URL=http://localhost:8095
Expand Down
1 change: 1 addition & 0 deletions dev/storage/src/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ class InMemoryTxAdapter extends DummyDbAdapter implements TxAdapter {
* @public
*/
export async function createInMemoryTxAdapter (
ctx: MeasureContext,
hierarchy: Hierarchy,
url: string,
workspace: WorkspaceId
Expand Down
26 changes: 16 additions & 10 deletions dev/tool/src/clean.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import chunter, { type ChatMessage } from '@hcengineering/chunter'
import contact from '@hcengineering/contact'
import core, {
DOMAIN_TX,
type MeasureContext,
SortingOrder,
TxOperations,
TxProcessor,
Expand All @@ -43,6 +44,7 @@ import { MongoClient } from 'mongodb'
export const DOMAIN_ACTIVITY = 'activity' as Domain

export async function cleanWorkspace (
ctx: MeasureContext,
mongoUrl: string,
workspaceId: WorkspaceId,
storageAdapter: StorageAdapter,
Expand All @@ -67,14 +69,14 @@ export async function cleanWorkspace (
attachments.map((it) => it.file).concat(contacts.map((it) => it.avatar).filter((it) => it) as string[])
)

const minioList = await storageAdapter.list(workspaceId)
const minioList = await storageAdapter.list(ctx, workspaceId)
const toClean: string[] = []
for (const mv of minioList) {
if (!files.has(mv.name)) {
toClean.push(mv.name)
if (!files.has(mv._id)) {
toClean.push(mv._id)
}
}
await storageAdapter.remove(workspaceId, toClean)
await storageAdapter.remove(ctx, workspaceId, toClean)
// connection.loadChunk(DOMAIN_BLOB, idx = )

if (opt.recruit) {
Expand Down Expand Up @@ -145,16 +147,20 @@ export async function cleanWorkspace (
}
}

export async function fixMinioBW (workspaceId: WorkspaceId, storageService: StorageAdapter): Promise<void> {
export async function fixMinioBW (
ctx: MeasureContext,
workspaceId: WorkspaceId,
storageService: StorageAdapter
): Promise<void> {
console.log('try clean bw miniature for ', workspaceId.name)
const from = new Date(new Date().setDate(new Date().getDate() - 7))
const list = await storageService.list(workspaceId)
const from = new Date(new Date().setDate(new Date().getDate() - 7)).getTime()
const list = await storageService.list(ctx, workspaceId)
console.log('found', list.length)
let removed = 0
for (const obj of list) {
if (obj.lastModified < from) continue
if (obj.name.includes('%size%')) {
await storageService.remove(workspaceId, [obj.name])
if (obj.modifiedOn < from) continue
if ((obj._id as string).includes('%size%')) {
await storageService.remove(ctx, workspaceId, [obj._id])
removed++
if (removed % 100 === 0) {
console.log('removed: ', removed)
Expand Down
12 changes: 7 additions & 5 deletions dev/tool/src/cleanOrphan.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { dropWorkspace, setWorkspaceDisabled, type Workspace } from '@hcengineering/account'
import core, { AccountRole, MeasureMetricsContext, SortingOrder } from '@hcengineering/core'
import core, { AccountRole, type MeasureContext, MeasureMetricsContext, SortingOrder } from '@hcengineering/core'
import contact from '@hcengineering/model-contact'
import { getWorkspaceDB } from '@hcengineering/mongo'
import { type StorageAdapter } from '@hcengineering/server-core'
import { connect } from '@hcengineering/server-tool'
import { type Db, type MongoClient } from 'mongodb'

export async function checkOrphanWorkspaces (
ctx: MeasureContext,
workspaces: Workspace[],
transactorUrl: string,
productId: string,
Expand Down Expand Up @@ -40,7 +41,7 @@ export async function checkOrphanWorkspaces (

// Find last transaction index:
const wspace = { name: ws.workspace, productId }
const hasBucket = await storageAdapter.exists(wspace)
const hasBucket = await storageAdapter.exists(ctx, wspace)
const [lastTx] = await connection.findAll(
core.class.Tx,
{
Expand Down Expand Up @@ -69,12 +70,13 @@ export async function checkOrphanWorkspaces (
const workspaceDb = getWorkspaceDB(client, { name: ws.workspace, productId })
await workspaceDb.dropDatabase()
if (storageAdapter !== undefined && hasBucket) {
const docs = await storageAdapter.list(wspace)
const docs = await storageAdapter.list(ctx, wspace)
await storageAdapter.remove(
ctx,
wspace,
docs.map((it) => it.name)
docs.map((it) => it._id)
)
await storageAdapter?.delete(wspace)
await storageAdapter.delete(ctx, wspace)
}
}
}
Expand Down
25 changes: 18 additions & 7 deletions dev/tool/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ export function devTool (

// We need to update workspaces with missing workspaceUrl
await checkOrphanWorkspaces(
toolCtx,
workspaces,
transactorUrl,
productId,
Expand Down Expand Up @@ -482,7 +483,6 @@ export function devTool (
program
.command('backup <dirName> <workspace>')
.description('dump workspace transactions and minio resources')
.requiredOption('-i --index <index>', 'Index name for elastic')
.option('-s, --skip <skip>', 'A list of ; separated domain names to skip during backup', '')
.option('-f, --force', 'Force backup', false)
.action(async (dirName: string, workspace: string, cmd: { skip: string, force: boolean }) => {
Expand Down Expand Up @@ -518,15 +518,20 @@ export function devTool (
.description('dump workspace transactions and minio resources')
.action(async (bucketName: string, dirName: string, workspace: string, cmd) => {
const { storageAdapter } = prepareTools()
const storage = await createStorageBackupStorage(storageAdapter, getWorkspaceId(bucketName, productId), dirName)
const storage = await createStorageBackupStorage(
toolCtx,
storageAdapter,
getWorkspaceId(bucketName, productId),
dirName
)
await backup(transactorUrl, getWorkspaceId(workspace, productId), storage)
})
program
.command('backup-s3-restore <bucketName> <dirName> <workspace> [date]')
.description('dump workspace transactions and minio resources')
.action(async (bucketName: string, dirName: string, workspace: string, date, cmd) => {
const { storageAdapter } = prepareTools()
const storage = await createStorageBackupStorage(storageAdapter, getWorkspaceId(bucketName), dirName)
const storage = await createStorageBackupStorage(toolCtx, storageAdapter, getWorkspaceId(bucketName), dirName)
await restore(transactorUrl, getWorkspaceId(workspace, productId), storage, parseInt(date ?? '-1'))
})
program
Expand All @@ -535,7 +540,12 @@ export function devTool (
.action(async (bucketName: string, dirName: string, cmd) => {
const { storageAdapter } = prepareTools()

const storage = await createStorageBackupStorage(storageAdapter, getWorkspaceId(bucketName, productId), dirName)
const storage = await createStorageBackupStorage(
toolCtx,
storageAdapter,
getWorkspaceId(bucketName, productId),
dirName
)
await backupList(storage)
})

Expand Down Expand Up @@ -576,7 +586,7 @@ export function devTool (
}

console.log(`clearing ${workspace} history:`)
await clearTelegramHistory(mongodbUri, getWorkspaceId(workspace, productId), telegramDB, minio)
await clearTelegramHistory(toolCtx, mongodbUri, getWorkspaceId(workspace, productId), telegramDB, minio)
})
})

Expand All @@ -596,7 +606,7 @@ export function devTool (

for (const w of workspaces) {
console.log(`clearing ${w.workspace} history:`)
await clearTelegramHistory(mongodbUri, getWorkspaceId(w.workspace, productId), telegramDB, minio)
await clearTelegramHistory(toolCtx, mongodbUri, getWorkspaceId(w.workspace, productId), telegramDB, minio)
}
})
})
Expand Down Expand Up @@ -624,6 +634,7 @@ export function devTool (
const { mongodbUri, storageAdapter: minio } = prepareTools()
await withDatabase(mongodbUri, async (db) => {
await cleanWorkspace(
toolCtx,
mongodbUri,
getWorkspaceId(workspace, productId),
minio,
Expand All @@ -636,7 +647,7 @@ export function devTool (

program.command('fix-bw-workspace <workspace>').action(async (workspace: string) => {
const { storageAdapter: minio } = prepareTools()
await fixMinioBW(getWorkspaceId(workspace, productId), minio)
await fixMinioBW(toolCtx, getWorkspaceId(workspace, productId), minio)
})

program
Expand Down
5 changes: 3 additions & 2 deletions dev/tool/src/telegram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// limitations under the License.
//

import { DOMAIN_TX, type Ref, type WorkspaceId } from '@hcengineering/core'
import { DOMAIN_TX, type MeasureContext, type Ref, type WorkspaceId } from '@hcengineering/core'
import { type StorageAdapter } from '@hcengineering/server-core'
import { DOMAIN_ATTACHMENT } from '@hcengineering/model-attachment'
import contact, { DOMAIN_CHANNEL } from '@hcengineering/model-contact'
Expand All @@ -29,6 +29,7 @@ const LastMessages = 'last-msgs'
* @public
*/
export async function clearTelegramHistory (
ctx: MeasureContext,
mongoUrl: string,
workspaceId: WorkspaceId,
tgDb: string,
Expand Down Expand Up @@ -90,7 +91,7 @@ export async function clearTelegramHistory (
workspaceDB.collection(DOMAIN_ATTACHMENT).deleteMany({
attachedToClass: telegram.class.Message
}),
storageAdapter.remove(workspaceId, Array.from(attachments))
storageAdapter.remove(ctx, workspaceId, Array.from(attachments))
])

console.log('clearing telegram service data...')
Expand Down
8 changes: 7 additions & 1 deletion models/core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export default mergeIds(coreId, core, {
Archived: '' as IntlString,
ClassLabel: '' as IntlString,
ClassPropertyLabel: '' as IntlString,
Members: '' as IntlString
Members: '' as IntlString,
Blob: '' as IntlString,
BlobContentType: '' as IntlString,
BlobEtag: '' as IntlString,
BlobVersion: '' as IntlString,
BlobStorageId: '' as IntlString,
BlobSize: '' as IntlString
}
})
31 changes: 31 additions & 0 deletions models/core/src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
//

import {
type Blob,
DOMAIN_BLOB,
DOMAIN_BLOB_DATA,
DOMAIN_CONFIGURATION,
DOMAIN_DOC_INDEX_STATE,
DOMAIN_FULLTEXT_BLOB,
Expand Down Expand Up @@ -63,6 +65,7 @@ import {
ReadOnly,
TypeBoolean,
TypeIntlString,
TypeNumber,
TypeRecord,
TypeRef,
TypeString,
Expand Down Expand Up @@ -129,6 +132,34 @@ export class TAttachedDoc extends TDoc implements AttachedDoc {
collection!: string
}

@Model(core.class.Blob, core.class.Doc, DOMAIN_BLOB_DATA)
@UX(core.string.Object)
export class TBlob extends TDoc implements Blob {
@Prop(TypeString(), core.string.Blob)
@ReadOnly()
provider!: string

@Prop(TypeString(), core.string.BlobContentType)
@ReadOnly()
contentType!: string

@Prop(TypeString(), core.string.BlobStorageId)
@ReadOnly()
storageId!: string

@Prop(TypeString(), core.string.BlobEtag)
@ReadOnly()
etag!: string

@Prop(TypeString(), core.string.BlobVersion)
@ReadOnly()
version!: string

@Prop(TypeNumber(), core.string.BlobSize)
@ReadOnly()
size!: number
}

@UX(core.string.ClassLabel)
@Model(core.class.Class, core.class.Doc, DOMAIN_MODEL)
export class TClass extends TDoc implements Class<Obj> {
Expand Down
4 changes: 3 additions & 1 deletion models/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {
TArrOf,
TAttachedDoc,
TAttribute,
TBlob,
TBlobData,
TClass,
TCollection,
Expand Down Expand Up @@ -151,7 +152,8 @@ export function createModel (builder: Builder): void {
TIndexConfiguration,
TStatus,
TStatusCategory,
TMigrationState
TMigrationState,
TBlob
)

builder.createDoc(
Expand Down
29 changes: 29 additions & 0 deletions packages/core/src/classes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,12 @@ export const DOMAIN_TRANSIENT = 'transient' as Domain
*/
export const DOMAIN_BLOB = 'blob' as Domain

/**
* Special domain to access s3 blob data.
* @public
*/
export const DOMAIN_BLOB_DATA = 'blob-data' as Domain

/**
* Special domain to access s3 blob data.
* @public
Expand Down Expand Up @@ -535,6 +541,29 @@ export interface IndexStageState extends Doc {
attributes: Record<string, any>
}

/**
* @public
*
* A blob document to manage blob attached documents.
*
* _id: is a platform ID and it created using our regular generateId(),
* and storageId is a provider specified storage id.
*/
export interface Blob extends Doc {
// Provider
provider: string
// A provider specific id
storageId: string
// A content type for blob
contentType: string
// A etag for blob
etag: string
// Document version if supported by provider
version: string | null
// A document size
size: number
}

/**
* @public
*
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
AnyAttribute,
ArrOf,
AttachedDoc,
Blob,
BlobData,
Class,
Collection,
Expand Down Expand Up @@ -82,6 +83,7 @@ export default plugin(coreId, {
class: {
Obj: '' as Ref<Class<Obj>>,
Doc: '' as Ref<Class<Doc>>,
Blob: '' as Ref<Class<Blob>>,
AttachedDoc: '' as Ref<Class<AttachedDoc>>,
Class: '' as Ref<Class<Class<Obj>>>,
Mixin: '' as Ref<Class<Mixin<Doc>>>,
Expand Down
4 changes: 3 additions & 1 deletion pods/backup/src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.
//

import { getWorkspaceId } from '@hcengineering/core'
import { getWorkspaceId, MeasureMetricsContext } from '@hcengineering/core'
import { MinioService } from '@hcengineering/minio'
import { setMetadata } from '@hcengineering/platform'
import { backup, createStorageBackupStorage } from '@hcengineering/server-backup'
Expand Down Expand Up @@ -92,10 +92,12 @@ export class PlatformWorker {

async backup (): Promise<void> {
const workspaces = await getWorkspaces()
const ctx = new MeasureMetricsContext('backup', {})
for (const ws of workspaces) {
console.log('\n\nBACKUP WORKSPACE ', ws.workspace, ws.productId)
try {
const storage = await createStorageBackupStorage(
ctx,
this.storageAdapter,
getWorkspaceId('backups', ws.productId),
ws.workspace
Expand Down
Loading