diff --git a/packages/storage/src/index.ts b/packages/storage/src/index.ts index 1eb91bff7a..2441dca1fb 100644 --- a/packages/storage/src/index.ts +++ b/packages/storage/src/index.ts @@ -60,12 +60,16 @@ export interface StorageAdapter { export interface StorageAdapterEx extends StorageAdapter { adapters?: Map + + syncBlobFromStorage: (ctx: MeasureContext, workspaceId: WorkspaceId, objectName: string) => Promise } /** * Ad dummy storage adapter for tests */ export class DummyStorageAdapter implements StorageAdapter, StorageAdapterEx { + async syncBlobFromStorage (ctx: MeasureContext, workspaceId: WorkspaceId, objectName: string): Promise {} + async initialize (ctx: MeasureContext, workspaceId: WorkspaceId): Promise {} async close (): Promise {} diff --git a/server/core/src/server/aggregator.ts b/server/core/src/server/aggregator.ts index 75767870ed..b04a2fac72 100644 --- a/server/core/src/server/aggregator.ts +++ b/server/core/src/server/aggregator.ts @@ -36,6 +36,28 @@ export class AggregatorStorageAdapter implements StorageAdapter, StorageAdapterE readonly dbAdapter: RawDBAdapter ) {} + async syncBlobFromStorage (ctx: MeasureContext, workspaceId: WorkspaceId, objectName: string): Promise { + const current = await this.dbAdapter.find( + ctx, + workspaceId, + DOMAIN_BLOB, + { _class: core.class.Blob, _id: objectName as Ref }, + { limit: 1 } + ) + const provider = this.adapters.get(current[0]?.provider ?? this.defaultAdapter) + if (provider === undefined) { + throw new NoSuchKeyError('No such provider found') + } + const stat = await provider.stat(ctx, workspaceId, objectName) + if (stat !== undefined) { + stat.provider = current[0]?.provider ?? this.defaultAdapter + if (current[0] !== undefined) { + await this.dbAdapter.clean(ctx, workspaceId, DOMAIN_BLOB, [current[0]._id]) + } + await this.dbAdapter.upload(ctx, workspaceId, DOMAIN_BLOB, [stat]) + } + } + async initialize (ctx: MeasureContext, workspaceId: WorkspaceId): Promise { // We need to initialize internal table if it miss documents. } @@ -219,7 +241,7 @@ export function buildStorage ( config: StorageConfiguration, dbAdapter: RawDBAdapter, storageFactory: (kind: string, config: StorageConfig) => StorageAdapter -): StorageAdapter { +): AggregatorStorageAdapter { const adapters = new Map() for (const c of config.storages) { adapters.set(c.name, storageFactory(c.kind, c)) diff --git a/server/server-storage/src/starter.ts b/server/server-storage/src/starter.ts index cfe82f583d..d8180d948c 100644 --- a/server/server-storage/src/starter.ts +++ b/server/server-storage/src/starter.ts @@ -1,7 +1,13 @@ import { MinioConfig, MinioService } from '@hcengineering/minio' import { createRawMongoDBAdapter } from '@hcengineering/mongo' import { S3Service, type S3Config } from '@hcengineering/s3' -import { StorageAdapter, StorageConfiguration, buildStorage, type StorageConfig } from '@hcengineering/server-core' +import { + AggregatorStorageAdapter, + StorageAdapter, + StorageConfiguration, + buildStorage, + type StorageConfig +} from '@hcengineering/server-core' import { addMinioFallback } from './minio' /* @@ -71,7 +77,7 @@ export function parseStorageEnv (storageEnv: string, storageConfig: StorageConfi } } -export function buildStorageFromConfig (config: StorageConfiguration, dbUrl: string): StorageAdapter { +export function buildStorageFromConfig (config: StorageConfiguration, dbUrl: string): AggregatorStorageAdapter { return buildStorage(config, createRawMongoDBAdapter(dbUrl), (kind, config): StorageAdapter => { if (kind === MinioService.config) { const c = config as MinioConfig