Desktop, CLI: Fix potential unresolved promise race conditions when scheduling the sync (#15216)

This commit is contained in:
mrjo118
2026-05-01 09:55:11 +01:00
committed by GitHub
parent 57bd5ff14a
commit ec85b1a7e6
3 changed files with 16 additions and 5 deletions
+1 -1
View File
@@ -248,7 +248,7 @@ class Command extends BaseCommand {
logger.info('Unsharing folder', folder.id);
await ShareService.instance().unshareFolder(folder.id);
await reg.scheduleSync();
await reg.waitForSyncFinishedThenSync();
};
if (args.command === 'add' || args.command === 'remove' || args.command === 'delete') {
@@ -12,6 +12,7 @@ import KvStore from '@joplin/lib/services/KvStore';
import ShareService from '@joplin/lib/services/share/ShareService';
import LabelledPasswordInput from '../PasswordInput/LabelledPasswordInput';
import shim from '@joplin/lib/shim';
import time from '@joplin/lib/time';
interface Props {
themeId: number;
@@ -24,6 +25,11 @@ enum Mode {
Reset = 2,
}
const syncAfterDefaultInterval = async () => {
await time.msleep(reg.defaultScheduleInterval());
await reg.waitForSyncFinishedThenSync();
};
export default function(props: Props) {
const [status, setStatus] = useState(MasterPasswordStatus.NotSet);
const [hasMasterPasswordEncryptedData, setHasMasterPasswordEncryptedData] = useState(true);
@@ -78,7 +84,8 @@ export default function(props: Props) {
} else {
throw new Error(`Unknown mode: ${mode}`);
}
void reg.waitForSyncFinishedThenSync(null);
// We need to defer the sync, as enabling encryption may take a few seconds to complete
void syncAfterDefaultInterval();
onClose();
} catch (error) {
void shim.showErrorDialog(error.message);
+7 -3
View File
@@ -81,6 +81,10 @@ class Registry {
}
}
public defaultScheduleInterval() {
return 1000 * 10;
}
public syncTarget = (syncTargetId: number = null) => {
if (syncTargetId === null) syncTargetId = Setting.value('sync.target');
if (this.syncTargets_[syncTargetId]) return this.syncTargets_[syncTargetId];
@@ -97,7 +101,7 @@ class Registry {
// This can be used when some data has been modified and we want to make
// sure it gets synced. So we wait for the current sync operation to
// finish (if one is running), then we trigger a sync just after.
public waitForSyncFinishedThenSync = async (delay: number | null = 0) => {
public waitForSyncFinishedThenSync = async () => {
if (!Setting.value('sync.target')) {
this.logger().info('waitForSyncFinishedThenSync - cancelling because no sync target is selected.');
return;
@@ -107,7 +111,7 @@ class Registry {
try {
const synchronizer = await this.syncTarget().synchronizer();
await synchronizer.waitForSyncToFinish();
await this.scheduleSync(delay);
await this.scheduleSync(0);
} finally {
this.waitForReSyncCalls_.pop();
}
@@ -118,7 +122,7 @@ class Registry {
this.schedSyncCalls_.push(true);
try {
if (delay === null) delay = 1000 * 10;
if (delay === null) delay = this.defaultScheduleInterval();
if (syncOptions === null) syncOptions = {};
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied