mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix(server): backward compatibility for beta+stable envs (#5510)
This commit is contained in:
@@ -19,5 +19,7 @@ if (node.prod && env.R2_OBJECT_STORAGE_ACCOUNT_ID) {
|
|||||||
`https://avatar.affineassets.com/${key}`;
|
`https://avatar.affineassets.com/${key}`;
|
||||||
|
|
||||||
AFFiNE.storage.storages.blob.provider = 'r2';
|
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'
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ export interface GetObjectMetadata {
|
|||||||
contentType: string;
|
contentType: string;
|
||||||
contentLength: number;
|
contentLength: number;
|
||||||
lastModified: Date;
|
lastModified: Date;
|
||||||
checksumCRC32: string;
|
checksumCRC32?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PutObjectMetadata {
|
export interface PutObjectMetadata {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class S3StorageProvider implements StorageProvider {
|
|||||||
config: S3StorageConfig,
|
config: S3StorageConfig,
|
||||||
public readonly bucket: string
|
public readonly bucket: string
|
||||||
) {
|
) {
|
||||||
this.client = new S3Client(config);
|
this.client = new S3Client({ region: 'auto', ...config });
|
||||||
this.logger = new Logger(`${S3StorageProvider.name}:${bucket}`);
|
this.logger = new Logger(`${S3StorageProvider.name}:${bucket}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +53,8 @@ export class S3StorageProvider implements StorageProvider {
|
|||||||
// metadata
|
// metadata
|
||||||
ContentType: metadata.contentType,
|
ContentType: metadata.contentType,
|
||||||
ContentLength: metadata.contentLength,
|
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
|
// always set when putting object
|
||||||
contentType: obj.ContentType!,
|
contentType: obj.ContentType!,
|
||||||
contentLength: obj.ContentLength!,
|
contentLength: obj.ContentLength!,
|
||||||
checksumCRC32: obj.ChecksumCRC32!,
|
|
||||||
lastModified: obj.LastModified!,
|
lastModified: obj.LastModified!,
|
||||||
|
checksumCRC32: obj.ChecksumCRC32,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -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 { Config } from '../../../config';
|
||||||
import { EventEmitter, type EventPayload, OnEvent } from '../../../event';
|
import { EventEmitter, type EventPayload, OnEvent } from '../../../event';
|
||||||
|
import { OctoBaseStorageModule } from '../../../storage';
|
||||||
import {
|
import {
|
||||||
BlobInputType,
|
BlobInputType,
|
||||||
createStorageProvider,
|
createStorageProvider,
|
||||||
StorageProvider,
|
StorageProvider,
|
||||||
} from '../providers';
|
} from '../providers';
|
||||||
|
import { toBuffer } from '../providers/utils';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class WorkspaceBlobStorage {
|
export class WorkspaceBlobStorage implements OnModuleInit {
|
||||||
public readonly provider: StorageProvider;
|
public readonly provider: StorageProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated for backwards compatibility, need to be removed in next stable release
|
||||||
|
*/
|
||||||
|
private octobase: Storage | null = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly event: EventEmitter,
|
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) {
|
async onModuleInit() {
|
||||||
return this.provider.put(`${workspaceId}/${key}`, blob);
|
if (!this.config.node.test) {
|
||||||
|
this.octobase = await OctoBaseStorageModule.Storage.connect(
|
||||||
|
this.config.db.url
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
get(workspaceId: string, key: string) {
|
async put(workspaceId: string, key: string, blob: BlobInputType) {
|
||||||
return this.provider.get(`${workspaceId}/${key}`);
|
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) {
|
async list(workspaceId: string) {
|
||||||
|
|||||||
@@ -53,7 +53,6 @@ export class WorkspacesController {
|
|||||||
res.setHeader('content-type', metadata.contentType);
|
res.setHeader('content-type', metadata.contentType);
|
||||||
res.setHeader('last-modified', metadata.lastModified.toISOString());
|
res.setHeader('last-modified', metadata.lastModified.toISOString());
|
||||||
res.setHeader('content-length', metadata.contentLength);
|
res.setHeader('content-length', metadata.contentLength);
|
||||||
res.setHeader('x-checksum-crc32', metadata.checksumCRC32);
|
|
||||||
} else {
|
} else {
|
||||||
this.logger.warn(`Blob ${workspaceId}/${name} has no metadata`);
|
this.logger.warn(`Blob ${workspaceId}/${name} has no metadata`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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';
|
import { createRequire } from 'node:module';
|
||||||
|
|
||||||
|
export const StorageProvide = Symbol('Storage');
|
||||||
|
|
||||||
let storageModule: typeof import('@affine/storage');
|
let storageModule: typeof import('@affine/storage');
|
||||||
try {
|
try {
|
||||||
storageModule = await import('@affine/storage');
|
storageModule = await import('@affine/storage');
|
||||||
@@ -14,6 +13,8 @@ try {
|
|||||||
: require('../../storage.node');
|
: require('../../storage.node');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export { storageModule as OctoBaseStorageModule };
|
||||||
|
|
||||||
export const mergeUpdatesInApplyWay = storageModule.mergeUpdatesInApplyWay;
|
export const mergeUpdatesInApplyWay = storageModule.mergeUpdatesInApplyWay;
|
||||||
|
|
||||||
export const verifyChallengeResponse = async (
|
export const verifyChallengeResponse = async (
|
||||||
|
|||||||
Reference in New Issue
Block a user