fix(server): backward compatibility for beta+stable envs (#5510)

This commit is contained in:
liuyi 2024-01-08 05:15:32 +00:00
parent b23c092953
commit d7b9462d1c
No known key found for this signature in database
GPG Key ID: 56709255DC7EC728
6 changed files with 61 additions and 17 deletions

View File

@ -19,5 +19,7 @@ if (node.prod && env.R2_OBJECT_STORAGE_ACCOUNT_ID) {
`https://avatar.affineassets.com/${key}`;
AFFiNE.storage.storages.blob.provider = 'r2';
AFFiNE.storage.storages.blob.bucket = 'workspace-blobs';
AFFiNE.storage.storages.blob.bucket = `workspace-blobs-${
AFFiNE.affine.canary ? 'canary' : 'prod'
}`;
}

View File

@ -9,7 +9,7 @@ export interface GetObjectMetadata {
contentType: string;
contentLength: number;
lastModified: Date;
checksumCRC32: string;
checksumCRC32?: string;
}
export interface PutObjectMetadata {

View File

@ -30,7 +30,7 @@ export class S3StorageProvider implements StorageProvider {
config: S3StorageConfig,
public readonly bucket: string
) {
this.client = new S3Client(config);
this.client = new S3Client({ region: 'auto', ...config });
this.logger = new Logger(`${S3StorageProvider.name}:${bucket}`);
}
@ -53,7 +53,8 @@ export class S3StorageProvider implements StorageProvider {
// metadata
ContentType: metadata.contentType,
ContentLength: metadata.contentLength,
ChecksumCRC32: metadata.checksumCRC32,
// TODO: Cloudflare doesn't support CRC32, use md5 instead later.
// ChecksumCRC32: metadata.checksumCRC32,
})
);
@ -90,8 +91,8 @@ export class S3StorageProvider implements StorageProvider {
// always set when putting object
contentType: obj.ContentType!,
contentLength: obj.ContentLength!,
checksumCRC32: obj.ChecksumCRC32!,
lastModified: obj.LastModified!,
checksumCRC32: obj.ChecksumCRC32,
},
};
} catch (e) {

View File

@ -1,29 +1,70 @@
import { Injectable } from '@nestjs/common';
import { Readable } from 'node:stream';
import type { Storage } from '@affine/storage';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Config } from '../../../config';
import { EventEmitter, type EventPayload, OnEvent } from '../../../event';
import { OctoBaseStorageModule } from '../../../storage';
import {
BlobInputType,
createStorageProvider,
StorageProvider,
} from '../providers';
import { toBuffer } from '../providers/utils';
@Injectable()
export class WorkspaceBlobStorage {
export class WorkspaceBlobStorage implements OnModuleInit {
public readonly provider: StorageProvider;
/**
* @deprecated for backwards compatibility, need to be removed in next stable release
*/
private octobase: Storage | null = null;
constructor(
private readonly event: EventEmitter,
{ storage }: Config
private readonly config: Config
) {
this.provider = createStorageProvider(storage, 'blob');
this.provider = createStorageProvider(this.config.storage, 'blob');
}
put(workspaceId: string, key: string, blob: BlobInputType) {
return this.provider.put(`${workspaceId}/${key}`, blob);
async onModuleInit() {
if (!this.config.node.test) {
this.octobase = await OctoBaseStorageModule.Storage.connect(
this.config.db.url
);
}
}
get(workspaceId: string, key: string) {
return this.provider.get(`${workspaceId}/${key}`);
async put(workspaceId: string, key: string, blob: BlobInputType) {
const buf = await toBuffer(blob);
await this.provider.put(`${workspaceId}/${key}`, buf);
if (this.octobase) {
await this.octobase.uploadBlob(workspaceId, buf);
}
}
async get(workspaceId: string, key: string) {
const result = await this.provider.get(`${workspaceId}/${key}`);
if (!result.body && this.octobase) {
const blob = await this.octobase.getBlob(workspaceId, key);
if (!blob) {
return result;
}
return {
body: Readable.from(blob.data),
metadata: {
contentType: blob.contentType,
contentLength: blob.size,
lastModified: new Date(blob.lastModified),
},
};
}
return result;
}
async list(workspaceId: string) {

View File

@ -53,7 +53,6 @@ export class WorkspacesController {
res.setHeader('content-type', metadata.contentType);
res.setHeader('last-modified', metadata.lastModified.toISOString());
res.setHeader('content-length', metadata.contentLength);
res.setHeader('x-checksum-crc32', metadata.checksumCRC32);
} else {
this.logger.warn(`Blob ${workspaceId}/${name} has no metadata`);
}

View File

@ -1,8 +1,7 @@
// NODE:
// This file has been deprecated after blob storage moved to cloudflare r2 storage.
// It only exists for backward compatibility.
import { createRequire } from 'node:module';
export const StorageProvide = Symbol('Storage');
let storageModule: typeof import('@affine/storage');
try {
storageModule = await import('@affine/storage');
@ -14,6 +13,8 @@ try {
: require('../../storage.node');
}
export { storageModule as OctoBaseStorageModule };
export const mergeUpdatesInApplyWay = storageModule.mergeUpdatesInApplyWay;
export const verifyChallengeResponse = async (