fix: data race when two try to set setting file

This commit is contained in:
lin onetwo 2024-01-01 13:10:36 +08:00
parent 4619af236c
commit ff7d6c115f
3 changed files with 17 additions and 21 deletions

View file

@ -6,7 +6,6 @@ import { MouseEvent, useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { WorkspaceSelectorBase } from './WorkspaceSelectorBase';
import defaultIcon from '@/images/default-icon.png';
import { PageType } from '@services/pages/interface';
import { WindowNames } from '@services/windows/WindowProperties';
import { useLocation } from 'wouter';

View file

@ -15,4 +15,5 @@ export const debouncedSetSettingFile = debounce(async (pages: Record<string, IPa
fixSettingFileWhenError(error as Error);
await settings.set(`pages`, pages as any);
}
}, 500);
// set to 800 instead of 500 to fix data race with src/services/workspaces/debouncedSetSettingFile.ts, when switch from wiki workspace to page, both will write to same file, and one will overwrite another
}, 800);

View file

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/require-await */
import settings from 'electron-settings';
import { injectable } from 'inversify';
import { debounce, mapValues, pickBy } from 'lodash';
import { mapValues, pickBy } from 'lodash';
import { lazyInject } from '@services/container';
import { logger } from '@services/libs/log';
@ -31,7 +31,6 @@ export class Pages implements IPagesService {
constructor() {
this.pages = this.getInitPagesForCache();
this.pages$ = new BehaviorSubject<IPage[]>(this.getPagesAsListSync());
this.updatePageSubject = debounce(this.updatePageSubject.bind(this), 500) as () => Promise<void>;
}
private async updatePageSubject(): Promise<void> {
@ -73,11 +72,8 @@ export class Pages implements IPagesService {
const oldActivePage = this.getActivePageSync();
const oldActivePageID = oldActivePage?.id;
logger.info(`setActivePage() closePage: ${oldActivePageID ?? 'undefined'}`);
if (id !== PageType.wiki) {
await this.workspaceViewService.clearActiveWorkspaceView();
}
if (oldActivePageID === id) return;
if (oldActivePageID === undefined) {
if (oldActivePageID === undefined || oldActivePageID === PageType.wiki) {
await this.update(id, { active: true });
} else {
if (id === PageType.wiki) {
@ -87,6 +83,12 @@ export class Pages implements IPagesService {
await this.updatePages({ [id]: { active: true }, [oldActivePageID]: { active: false } });
}
}
if (id !== PageType.wiki) {
// delay this so the page state can be updated first
setTimeout(() => {
void this.workspaceViewService.clearActiveWorkspaceView();
}, 0);
}
}
public async clearActivePage(id: string | PageType | undefined): Promise<void> {
@ -113,13 +115,11 @@ export class Pages implements IPagesService {
}
public async set(id: string | PageType, page: IPage, updateSettingFile = true): Promise<void> {
logger.info(`set page ${id} with ${JSON.stringify(page)}`);
logger.info(`set page ${id} with ${JSON.stringify(page)}`, { updateSettingFile });
this.pages[id] = page;
if (updateSettingFile) {
await Promise.all([
debouncedSetSettingFile(this.pages),
this.updatePageSubject(),
]);
await this.updatePageSubject();
void debouncedSetSettingFile(this.pages);
}
}
@ -136,20 +136,16 @@ export class Pages implements IPagesService {
for (const id in newPages) {
await this.set(id, newPages[id], false);
}
await Promise.all([
debouncedSetSettingFile(this.pages),
this.updatePageSubject(),
]);
await this.updatePageSubject();
void debouncedSetSettingFile(this.pages);
}
public async updatePages(newPages: Record<string, Partial<IPage>>): Promise<void> {
for (const id in newPages) {
await this.update(id, newPages[id], false);
}
await Promise.all([
debouncedSetSettingFile(this.pages),
this.updatePageSubject(),
]);
await this.updatePageSubject();
void debouncedSetSettingFile(this.pages);
}
/**