Skip to content

Commit 9b63ba8

Browse files
authored
fix: mounting home fs multiple times will throw error (#175)
1 parent cae8423 commit 9b63ba8

3 files changed

Lines changed: 69 additions & 37 deletions

File tree

packages/common/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './mutex';
12
export * from './request';
23
export * from './types';

packages/common/src/mutex.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export class Mutex {
2+
private mutex = Promise.resolve();
3+
4+
lock(): PromiseLike<() => void> {
5+
let begin: (unlock: () => void) => void = () => {};
6+
7+
this.mutex = this.mutex.then(() => new Promise(begin));
8+
9+
return new Promise((res) => {
10+
begin = res;
11+
});
12+
}
13+
14+
async dispatch<T>(fn: () => PromiseLike<T>): Promise<T> {
15+
const unlock = await this.lock();
16+
try {
17+
return await Promise.resolve(fn());
18+
} finally {
19+
unlock();
20+
}
21+
}
22+
}
Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { Deferred, getDebugLogger } from '@opensumi/ide-core-common';
1+
import { Mutex } from '@codeblitzjs/ide-common';
2+
import { Deferred, Disposable, getDebugLogger } from '@opensumi/ide-core-common';
23
import { HOME_IDB_NAME, HOME_ROOT } from '../../common';
34
import { RootFS } from '../../common/types';
4-
import { BrowserFS, FileSystem } from '../node';
5+
import { BrowserFS, FileSystem, isPathMounted } from '../node';
56

67
const { createFileSystem, FileSystem, initialize } = BrowserFS;
78

@@ -11,18 +12,18 @@ export const filesystemDeferred = new Deferred<void>();
1112
export const isFilesystemReady = () => filesystemDeferred.promise;
1213

1314
let mountfs: RootFS | null = null;
14-
let mountfsDeferred: Deferred<RootFS> | null = null;
15+
let mountRootFsMutex = new Mutex();
1516

1617
export const initializeRootFileSystem = async () => {
17-
if (mountfsDeferred) return mountfsDeferred.promise;
18+
return mountRootFsMutex.dispatch(async () => {
19+
if (mountfs) return mountfs;
1820

19-
mountfsDeferred = new Deferred<RootFS>();
20-
mountfs = (await createFileSystem(FileSystem.MountableFileSystem, {})) as RootFS;
21-
mountfsDeferred.resolve(mountfs);
21+
mountfs = (await createFileSystem(FileSystem.MountableFileSystem, {})) as RootFS;
2222

23-
initialize(mountfs);
24-
filesystemDeferred.resolve();
25-
return mountfs;
23+
initialize(mountfs);
24+
filesystemDeferred.resolve();
25+
return mountfs;
26+
});
2627
};
2728

2829
export const unmountRootFS = () => {
@@ -32,34 +33,42 @@ export const unmountRootFS = () => {
3233
}
3334
};
3435

36+
const initHomeFsMutex = new Mutex();
37+
3538
export const initializeHomeFileSystem = async (rootFS: RootFS, scenario?: string | null) => {
36-
try {
37-
let homefs: FileSystem | null = null;
38-
// scenario 为 null 时 或者 browser 隐身模式时无法使用 indexedDB 时,回退到 memory
39-
// TODO: 寻找更好的解决方案
40-
if (scenario !== null && FileSystem.IndexedDB.isAvailable()) {
41-
try {
42-
// 通过 scenario 隔离 indexedDB
43-
homefs = await createFileSystem(FileSystem.IndexedDB, {
44-
storeName: `${HOME_IDB_NAME}${scenario ? `/${scenario}` : ''}`,
45-
});
46-
} catch (err) {
47-
// @ts-ignore
48-
getDebugLogger().error(`初始化 indexedDB 文件系统失败 ${err?.message || ''}`);
49-
homefs = null;
50-
}
39+
return await initHomeFsMutex.dispatch(async () => {
40+
// 如果用户使用了多个 codeblitz 实例,第一个挂载的先生效
41+
if (isPathMounted(rootFS, HOME_ROOT)) {
42+
return Disposable.NULL;
5143
}
52-
if (!homefs) {
53-
homefs = await createFileSystem(FileSystem.InMemory, {});
44+
45+
try {
46+
let homefs: FileSystem | null = null;
47+
// scenario 为 null 时 或者 browser 隐身模式时无法使用 indexedDB 时,回退到 memory
48+
// TODO: 寻找更好的解决方案
49+
if (scenario !== null && FileSystem.IndexedDB.isAvailable()) {
50+
try {
51+
// 通过 scenario 隔离 indexedDB
52+
homefs = await createFileSystem(FileSystem.IndexedDB, {
53+
storeName: `${HOME_IDB_NAME}${scenario ? `/${scenario}` : ''}`,
54+
});
55+
} catch (err) {
56+
getDebugLogger().error(`初始化 indexedDB 文件系统失败 ${(err as Error)?.message || ''}`);
57+
homefs = null;
58+
}
59+
}
60+
if (!homefs) {
61+
homefs = await createFileSystem(FileSystem.InMemory, {});
62+
}
63+
rootFS.mount(HOME_ROOT, homefs);
64+
} catch (err) {
65+
getDebugLogger().error(`初始化 home 目录失败 ${(err as Error)?.message || ''}`);
5466
}
55-
rootFS.mount(HOME_ROOT, homefs);
56-
} catch (err) {
57-
// @ts-ignore
58-
getDebugLogger().error(`初始化 home 目录失败 ${err?.message || ''}`);
59-
}
60-
return {
61-
dispose() {
62-
rootFS.umount(HOME_ROOT);
63-
},
64-
};
67+
68+
return {
69+
dispose() {
70+
rootFS.umount(HOME_ROOT);
71+
},
72+
};
73+
});
6574
};

0 commit comments

Comments
 (0)