mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-23 13:02:21 +08:00
feat(server): lightweight s3 client (#14348)
#### PR Dependency Tree * **PR #14348** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a dedicated S3-compatible client package and expanded S3-compatible storage config (endpoint, region, forcePathStyle, requestTimeoutMs, minPartSize, presign options, sessionToken). * Document sync now broadcasts batched/compressed doc updates for more efficient real-time syncing. * **Tests** * New unit and benchmark tests for base64 utilities and S3 multipart listing; updated storage-related tests to match new formats. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
import { bench, describe } from 'vitest';
|
||||
|
||||
import { base64ToUint8Array, uint8ArrayToBase64 } from '../impls/cloud/socket';
|
||||
|
||||
const data = new Uint8Array(1024 * 256);
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
data[i] = i % 251;
|
||||
}
|
||||
let encoded = '';
|
||||
|
||||
await uint8ArrayToBase64(data).then(result => {
|
||||
encoded = result;
|
||||
});
|
||||
|
||||
describe('base64 helpers', () => {
|
||||
bench('encode Uint8Array to base64', async () => {
|
||||
await uint8ArrayToBase64(data);
|
||||
});
|
||||
|
||||
bench('decode base64 to Uint8Array', () => {
|
||||
base64ToUint8Array(encoded);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { base64ToUint8Array, uint8ArrayToBase64 } from '../impls/cloud/socket';
|
||||
|
||||
function makeSample(size: number) {
|
||||
const data = new Uint8Array(size);
|
||||
for (let i = 0; i < size; i++) {
|
||||
data[i] = i % 251;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
describe('base64 helpers', () => {
|
||||
test('roundtrip preserves data', async () => {
|
||||
const input = makeSample(1024);
|
||||
const encoded = await uint8ArrayToBase64(input);
|
||||
const decoded = base64ToUint8Array(encoded);
|
||||
expect(decoded).toEqual(input);
|
||||
});
|
||||
|
||||
test('handles large payloads', async () => {
|
||||
const input = makeSample(256 * 1024);
|
||||
const encoded = await uint8ArrayToBase64(input);
|
||||
const decoded = base64ToUint8Array(encoded);
|
||||
expect(decoded).toEqual(input);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { CloudDocStorage } from '../impls/cloud/doc';
|
||||
|
||||
const base64UpdateA = 'AQID';
|
||||
const base64UpdateB = 'BAUG';
|
||||
|
||||
describe('CloudDocStorage broadcast updates', () => {
|
||||
test('emits updates from batch payload', () => {
|
||||
const storage = new CloudDocStorage({
|
||||
id: 'space-1',
|
||||
serverBaseUrl: 'http://localhost',
|
||||
isSelfHosted: true,
|
||||
type: 'workspace',
|
||||
readonlyMode: true,
|
||||
});
|
||||
|
||||
(storage as any).connection.idConverter = {
|
||||
oldIdToNewId: (id: string) => id,
|
||||
newIdToOldId: (id: string) => id,
|
||||
};
|
||||
|
||||
const received: Uint8Array[] = [];
|
||||
storage.subscribeDocUpdate(update => {
|
||||
received.push(update.bin);
|
||||
});
|
||||
|
||||
storage.onServerUpdates({
|
||||
spaceType: 'workspace',
|
||||
spaceId: 'space-1',
|
||||
docId: 'doc-1',
|
||||
updates: [base64UpdateA, base64UpdateB],
|
||||
timestamp: Date.now(),
|
||||
});
|
||||
|
||||
expect(received).toEqual([
|
||||
new Uint8Array([1, 2, 3]),
|
||||
new Uint8Array([4, 5, 6]),
|
||||
]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user