chore: bump blocksuite (#7075)

## Features
- toeverything/blocksuite#6937 @Flrande

## Bugfix
- toeverything/blocksuite#7137 @fundon
- toeverything/blocksuite#7126 @golok727
- toeverything/blocksuite#7128 @CatsJuice
- toeverything/blocksuite#7130 @fundon

## Refactor

## Misc
- toeverything/blocksuite#7131 @fundon

## Additional changes

Adjust the awareness provider so that it only obtains awareness instances when connect, and fixes the dependencies between workspace components.
This commit is contained in:
EYHN
2024-05-27 05:11:12 +00:00
parent 5552c02e4a
commit a440e85ffe
24 changed files with 192 additions and 194 deletions
+2 -2
View File
@@ -3,8 +3,8 @@
"private": true,
"type": "module",
"devDependencies": {
"@blocksuite/global": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/store": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/global": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/store": "0.15.0-canary-202405261009-6c8ef5b",
"react": "18.3.1",
"react-dom": "18.3.1",
"vitest": "1.6.0"
+5 -5
View File
@@ -13,9 +13,9 @@
"@affine/debug": "workspace:*",
"@affine/env": "workspace:*",
"@affine/templates": "workspace:*",
"@blocksuite/blocks": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/global": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/store": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/blocks": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/global": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/store": "0.15.0-canary-202405261009-6c8ef5b",
"@datastructures-js/binary-search-tree": "^5.3.2",
"foxact": "^0.2.33",
"jotai": "^2.8.0",
@@ -30,8 +30,8 @@
"devDependencies": {
"@affine-test/fixtures": "workspace:*",
"@affine/templates": "workspace:*",
"@blocksuite/block-std": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/presets": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/block-std": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/presets": "0.15.0-canary-202405261009-6c8ef5b",
"@testing-library/react": "^15.0.0",
"async-call-rpc": "^6.4.0",
"react": "^18.2.0",
@@ -34,7 +34,7 @@ export class WorkspaceEngine extends Entity<{
start() {
this.doc.start();
this.awareness.connect();
this.awareness.connect(this.workspaceService.workspace.awareness);
this.blob.start();
}
@@ -78,11 +78,11 @@ export class WorkspaceUpgrade extends Entity {
this.workspaceService.workspace.docCollection.schema
);
const blobList =
await this.workspaceService.workspace.docCollection.blob.list();
await this.workspaceService.workspace.docCollection.blobSync.list();
for (const blobKey of blobList) {
const blob =
await this.workspaceService.workspace.docCollection.blob.get(
await this.workspaceService.workspace.docCollection.blobSync.get(
blobKey
);
if (blob) {
@@ -29,24 +29,9 @@ export class Workspace extends Entity {
if (!this._docCollection) {
this._docCollection = new DocCollection({
id: this.openOptions.metadata.id,
blobStorages: [
() => ({
crud: {
get: key => {
return this.engine.blob.get(key);
},
set: (key, value) => {
return this.engine.blob.set(key, value);
},
list: () => {
return this.engine.blob.list();
},
delete: key => {
return this.engine.blob.delete(key);
},
},
}),
],
blobSources: {
main: this.engine.blob,
},
idGenerator: () => nanoid(),
schema: globalBlockSuiteSchema,
});
@@ -69,7 +69,7 @@ export function configureWorkspaceModule(framework: Framework) {
.scope(WorkspaceScope)
.service(WorkspaceService)
.entity(Workspace, [WorkspaceScope])
.service(WorkspaceEngineService, [WorkspaceService])
.service(WorkspaceEngineService, [WorkspaceScope])
.entity(WorkspaceEngine, [WorkspaceService])
.service(WorkspaceUpgradeService)
.entity(WorkspaceUpgrade, [
@@ -10,7 +10,6 @@ import type {
DocStorage,
} from '../../../sync';
import type { WorkspaceProfileInfo } from '../entities/profile';
import type { Workspace } from '../entities/workspace';
import type { WorkspaceMetadata } from '../metadata';
export interface WorkspaceEngineProvider {
@@ -54,7 +53,7 @@ export interface WorkspaceFlavourProvider {
getWorkspaceBlob(id: string, blob: string): Promise<Blob | null>;
getEngineProvider(workspace: Workspace): WorkspaceEngineProvider;
getEngineProvider(workspaceId: string): WorkspaceEngineProvider;
}
export const WorkspaceFlavourProvider =
@@ -1,6 +1,6 @@
import { Service } from '../../../framework';
import { WorkspaceEngine } from '../entities/engine';
import type { WorkspaceService } from './workspace';
import type { WorkspaceScope } from '../scopes/workspace';
export class WorkspaceEngineService extends Service {
private _engine: WorkspaceEngine | null = null;
@@ -8,15 +8,15 @@ export class WorkspaceEngineService extends Service {
if (!this._engine) {
this._engine = this.framework.createEntity(WorkspaceEngine, {
engineProvider:
this.workspaceService.workspace.flavourProvider.getEngineProvider(
this.workspaceService.workspace
this.workspaceScope.props.flavourProvider.getEngineProvider(
this.workspaceScope.props.openOptions.metadata.id
),
});
}
return this._engine;
}
constructor(private readonly workspaceService: WorkspaceService) {
constructor(private readonly workspaceScope: WorkspaceScope) {
super();
}
}
@@ -10,7 +10,6 @@ import { type BlobStorage, MemoryDocStorage } from '../../../sync';
import { MemoryBlobStorage } from '../../../sync/blob/blob';
import type { GlobalState } from '../../storage';
import type { WorkspaceProfileInfo } from '../entities/profile';
import type { Workspace } from '../entities/workspace';
import { globalBlockSuiteSchema } from '../global-schema';
import type { WorkspaceMetadata } from '../metadata';
import type {
@@ -54,13 +53,9 @@ export class TestingWorkspaceLocalProvider
id: id,
idGenerator: () => nanoid(),
schema: globalBlockSuiteSchema,
blobStorages: [
() => {
return {
crud: blobStorage,
};
},
],
blobSources: {
main: blobStorage,
},
});
// apply initial state
@@ -110,7 +105,7 @@ export class TestingWorkspaceLocalProvider
blob
);
}
getEngineProvider(workspace: Workspace): WorkspaceEngineProvider {
getEngineProvider(workspaceId: string): WorkspaceEngineProvider {
return {
getDocStorage: () => {
return this.docStorage;
@@ -123,7 +118,7 @@ export class TestingWorkspaceLocalProvider
},
getLocalBlobStorage: () => {
return new MemoryBlobStorage(
wrapMemento(this.store, workspace.id + '/blobs/')
wrapMemento(this.store, workspaceId + '/blobs/')
);
},
getRemoteBlobStorages() {
+5 -3
View File
@@ -1,13 +1,15 @@
import type { Awareness } from 'y-protocols/awareness.js';
export interface AwarenessConnection {
connect(): void;
connect(awareness: Awareness): void;
disconnect(): void;
}
export class AwarenessEngine {
constructor(public readonly connections: AwarenessConnection[]) {}
connect() {
this.connections.forEach(connection => connection.connect());
connect(awareness: Awareness) {
this.connections.forEach(connection => connection.connect(awareness));
}
disconnect() {
@@ -29,6 +29,9 @@ export interface BlobStatus {
* all operations priority use local, then use remote.
*/
export class BlobEngine {
readonly name = 'blob-engine';
readonly readonly = this.local.readonly;
private abort: AbortController | null = null;
readonly isStorageOverCapacity$ = new LiveData(false);
+5 -5
View File
@@ -75,12 +75,12 @@
"zod": "^3.22.4"
},
"devDependencies": {
"@blocksuite/block-std": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/blocks": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/global": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/block-std": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/blocks": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/global": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/icons": "2.1.51",
"@blocksuite/presets": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/store": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/presets": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/store": "0.15.0-canary-202405261009-6c8ef5b",
"@storybook/addon-actions": "^7.6.17",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-interactions": "^7.6.17",
+6 -6
View File
@@ -18,13 +18,13 @@
"@affine/graphql": "workspace:*",
"@affine/i18n": "workspace:*",
"@affine/templates": "workspace:*",
"@blocksuite/block-std": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/blocks": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/global": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/block-std": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/blocks": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/global": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/icons": "2.1.51",
"@blocksuite/inline": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/presets": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/store": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/inline": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/presets": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/store": "0.15.0-canary-202405261009-6c8ef5b",
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/modifiers": "^7.0.0",
"@dnd-kit/sortable": "^8.0.0",
@@ -108,11 +108,9 @@ const getOrCreateShellWorkspace = (workspaceId: string) => {
const blobStorage = new CloudBlobStorage(workspaceId);
docCollection = new DocCollection({
id: workspaceId,
blobStorages: [
() => ({
crud: blobStorage,
}),
],
blobSources: {
main: blobStorage,
},
schema: globalBlockSuiteSchema,
});
docCollectionMap.set(workspaceId, docCollection);
@@ -64,7 +64,7 @@ export const ProfilePanel = () => {
}
try {
const reducedFile = await validateAndReduceImage(file);
const blobs = workspace.docCollection.blob;
const blobs = workspace.docCollection.blobSync;
const blobId = await blobs.set(reducedFile);
workspace.docCollection.meta.setAvatar(blobId);
} catch (error) {
@@ -190,7 +190,7 @@ const ImagePreviewModalImpl = (
if (typeof blockId === 'string') {
const block = page.getBlockById(blockId) as ImageBlockModel;
assertExists(block);
const store = block.page.blob;
const store = block.page.blobSync;
const url = store?.get(block.sourceId as string);
const img = await url;
if (!img) {
@@ -260,7 +260,7 @@ const ImagePreviewModalImpl = (
assertExists(page);
const block = page.getBlockById(blockId) as ImageBlockModel;
assertExists(block);
return props.docCollection.blob.get(block?.sourceId as string);
return props.docCollection.blobSync.get(block?.sourceId as string);
},
suspense: true,
}
@@ -18,7 +18,6 @@ import {
onComplete,
OnEvent,
onStart,
type Workspace,
type WorkspaceEngineProvider,
type WorkspaceFlavourProvider,
type WorkspaceMetadata,
@@ -96,7 +95,9 @@ export class CloudWorkspaceFlavourProviderService
id: tempId,
idGenerator: () => nanoid(),
schema: globalBlockSuiteSchema,
blobStorages: [() => ({ crud: blobStorage })],
blobSources: {
main: blobStorage,
},
});
// apply initial state
@@ -223,35 +224,31 @@ export class CloudWorkspaceFlavourProviderService
const cloudBlob = new CloudBlobStorage(id);
return await cloudBlob.get(blob);
}
getEngineProvider(workspace: Workspace): WorkspaceEngineProvider {
getEngineProvider(workspaceId: string): WorkspaceEngineProvider {
return {
getAwarenessConnections: () => {
return [
new BroadcastChannelAwarenessConnection(
workspace.id,
workspace.awareness
),
new BroadcastChannelAwarenessConnection(workspaceId),
new CloudAwarenessConnection(
workspace.id,
workspace.awareness,
workspaceId,
this.webSocketService.newSocket()
),
];
},
getDocServer: () => {
return new CloudDocEngineServer(
workspace.id,
workspaceId,
this.webSocketService.newSocket()
);
},
getDocStorage: () => {
return this.storageProvider.getDocStorage(workspace.id);
return this.storageProvider.getDocStorage(workspaceId);
},
getLocalBlobStorage: () => {
return this.storageProvider.getBlobStorage(workspace.id);
return this.storageProvider.getBlobStorage(workspaceId);
},
getRemoteBlobStorages() {
return [new CloudBlobStorage(workspace.id)];
return [new CloudBlobStorage(workspaceId)];
},
};
}
@@ -15,34 +15,32 @@ export class BroadcastChannelAwarenessConnection
implements AwarenessConnection
{
channel: BroadcastChannel | null = null;
awareness: Awareness | null = null;
constructor(
private readonly workspaceId: string,
private readonly awareness: Awareness
) {}
constructor(private readonly workspaceId: string) {}
connect(): void {
connect(awareness: Awareness): void {
this.awareness = awareness;
this.channel = new BroadcastChannel('awareness:' + this.workspaceId);
this.channel.postMessage({
type: 'connect',
} satisfies ChannelMessage);
this.awareness.on('update', (changes: AwarenessChanges, origin: unknown) =>
this.handleAwarenessUpdate(changes, origin)
);
this.channel.addEventListener(
'message',
(event: MessageEvent<ChannelMessage>) => {
this.handleChannelMessage(event);
}
);
this.awareness.on('update', this.handleAwarenessUpdate);
this.channel.addEventListener('message', this.handleChannelMessage);
}
disconnect(): void {
this.channel?.close();
this.channel = null;
this.awareness?.off('update', this.handleAwarenessUpdate);
this.awareness = null;
}
handleAwarenessUpdate(changes: AwarenessChanges, origin: unknown) {
handleAwarenessUpdate = (changes: AwarenessChanges, origin: unknown) => {
if (this.awareness === null) {
return;
}
if (origin === 'remote') {
return;
}
@@ -56,9 +54,13 @@ export class BroadcastChannelAwarenessConnection
type: 'update',
update: update,
} satisfies ChannelMessage);
}
};
handleChannelMessage = (event: MessageEvent<ChannelMessage>) => {
if (this.awareness === null) {
return;
}
handleChannelMessage(event: MessageEvent<ChannelMessage>) {
if (event.data.type === 'update') {
const update = event.data.update;
applyAwarenessUpdate(this.awareness, update, 'remote');
@@ -71,5 +73,5 @@ export class BroadcastChannelAwarenessConnection
]),
} satisfies ChannelMessage);
}
}
};
}
@@ -15,23 +15,25 @@ const logger = new DebugLogger('affine:awareness:socketio');
type AwarenessChanges = Record<'added' | 'updated' | 'removed', number[]>;
export class CloudAwarenessConnection implements AwarenessConnection {
awareness: Awareness | null = null;
constructor(
private readonly workspaceId: string,
private readonly awareness: Awareness,
private readonly socket: Socket
) {}
connect(): void {
connect(awareness: Awareness): void {
this.socket.on('server-awareness-broadcast', this.awarenessBroadcast);
this.socket.on(
'new-client-awareness-init',
this.newClientAwarenessInitHandler
);
this.awareness = awareness;
this.awareness.on('update', this.awarenessUpdate);
window.addEventListener('beforeunload', this.windowBeforeUnloadHandler);
this.socket.on('connect', () => this.handleConnect());
this.socket.on('connect', this.handleConnect);
this.socket.on('server-version-rejected', this.handleReject);
if (this.socket.connected) {
@@ -42,12 +44,16 @@ export class CloudAwarenessConnection implements AwarenessConnection {
}
disconnect(): void {
removeAwarenessStates(
this.awareness,
[this.awareness.clientID],
'disconnect'
);
this.awareness.off('update', this.awarenessUpdate);
if (this.awareness) {
removeAwarenessStates(
this.awareness,
[this.awareness.clientID],
'disconnect'
);
this.awareness.off('update', this.awarenessUpdate);
}
this.awareness = null;
this.socket.emit('client-leave-awareness', this.workspaceId);
this.socket.off('server-awareness-broadcast', this.awarenessBroadcast);
this.socket.off(
@@ -66,6 +72,9 @@ export class CloudAwarenessConnection implements AwarenessConnection {
workspaceId: string;
awarenessUpdate: string;
}) => {
if (!this.awareness) {
return;
}
if (wsId !== this.workspaceId) {
return;
}
@@ -77,6 +86,10 @@ export class CloudAwarenessConnection implements AwarenessConnection {
};
awarenessUpdate = (changes: AwarenessChanges, origin: unknown) => {
if (!this.awareness) {
return;
}
if (origin === 'remote') {
return;
}
@@ -97,6 +110,10 @@ export class CloudAwarenessConnection implements AwarenessConnection {
};
newClientAwarenessInitHandler = () => {
if (!this.awareness) {
return;
}
const awarenessUpdate = encodeAwarenessUpdate(this.awareness, [
this.awareness.clientID,
]);
@@ -111,6 +128,10 @@ export class CloudAwarenessConnection implements AwarenessConnection {
};
windowBeforeUnloadHandler = () => {
if (!this.awareness) {
return;
}
removeAwarenessStates(
this.awareness,
[this.awareness.clientID],
@@ -3,7 +3,6 @@ import { WorkspaceFlavour } from '@affine/env/workspace';
import { DocCollection } from '@blocksuite/store';
import type {
BlobStorage,
Workspace,
WorkspaceEngineProvider,
WorkspaceFlavourProvider,
WorkspaceMetadata,
@@ -68,7 +67,7 @@ export class LocalWorkspaceFlavourProvider
id: id,
idGenerator: () => nanoid(),
schema: globalBlockSuiteSchema,
blobStorages: [() => ({ crud: blobStorage })],
blobSources: { main: blobStorage },
});
// apply initial state
@@ -153,24 +152,19 @@ export class LocalWorkspaceFlavourProvider
return this.storageProvider.getBlobStorage(id).get(blob);
}
getEngineProvider(workspace: Workspace): WorkspaceEngineProvider {
getEngineProvider(workspaceId: string): WorkspaceEngineProvider {
return {
getAwarenessConnections() {
return [
new BroadcastChannelAwarenessConnection(
workspace.id,
workspace.awareness
),
];
return [new BroadcastChannelAwarenessConnection(workspaceId)];
},
getDocServer() {
return null;
},
getDocStorage: () => {
return this.storageProvider.getDocStorage(workspace.id);
return this.storageProvider.getDocStorage(workspaceId);
},
getLocalBlobStorage: () => {
return this.storageProvider.getBlobStorage(workspace.id);
return this.storageProvider.getBlobStorage(workspaceId);
},
getRemoteBlobStorages() {
return [];
@@ -138,11 +138,11 @@ export const Component = () => {
},
{
...defaultCloudProvider,
getEngineProvider(workspace) {
getEngineProvider(workspaceId) {
return {
getDocStorage() {
return new ReadonlyDocStorage({
[workspace.id]: new Uint8Array(workspaceArrayBuffer),
[workspaceId]: new Uint8Array(workspaceArrayBuffer),
[docId]: new Uint8Array(pageArrayBuffer),
});
},
@@ -156,7 +156,7 @@ export const Component = () => {
return EmptyBlobStorage;
},
getRemoteBlobStorages() {
return [new CloudBlobStorage(workspace.id)];
return [new CloudBlobStorage(workspaceId)];
},
};
},
+4 -4
View File
@@ -29,10 +29,10 @@
"@affine/env": "workspace:*",
"@affine/i18n": "workspace:*",
"@affine/native": "workspace:*",
"@blocksuite/block-std": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/blocks": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/presets": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/store": "0.15.0-canary-202405240632-44ff286",
"@blocksuite/block-std": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/blocks": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/presets": "0.15.0-canary-202405261009-6c8ef5b",
"@blocksuite/store": "0.15.0-canary-202405261009-6c8ef5b",
"@electron-forge/cli": "^7.3.0",
"@electron-forge/core": "^7.3.0",
"@electron-forge/core-utils": "^7.3.0",