Skip to content

Commit cc36b3f

Browse files
authored
fix(replicache): Wrap persist in a lock. (#3577)
This was triggered in the zero perf benchmark which calls persist. Sometimes this call got overlapped with the scheduled persist call which raised the assert. Instead of asserting in this condition we wait until the current persist operation is done.
1 parent 936ac9b commit cc36b3f

File tree

2 files changed

+10
-15
lines changed

2 files changed

+10
-15
lines changed

packages/replicache/src/replicache-impl.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {Lock} from '@rocicorp/lock';
12
import {consoleLogSink, LogContext} from '@rocicorp/logger';
23
import {resolver} from '@rocicorp/resolver';
34
import {AbortError} from '../../shared/src/abort-error.js';
@@ -291,7 +292,7 @@ export class ReplicacheImpl<MD extends MutatorDefs = {}> {
291292

292293
readonly #closeAbortController = new AbortController();
293294

294-
#persistIsRunning = false;
295+
readonly #persistLock = new Lock();
295296
readonly #enableScheduledPersist: boolean;
296297
readonly #enableScheduledRefresh: boolean;
297298
readonly #enablePullAndPushInOpen: boolean;
@@ -1131,10 +1132,9 @@ export class ReplicacheImpl<MD extends MutatorDefs = {}> {
11311132
return {requestID, syncHead, ok: httpRequestInfo.httpStatusCode === 200};
11321133
}
11331134

1134-
async persist(): Promise<void> {
1135-
assert(!this.#persistIsRunning);
1136-
this.#persistIsRunning = true;
1137-
try {
1135+
persist(): Promise<void> {
1136+
// Prevent multiple persist calls from running at the same time.
1137+
return this.#persistLock.withLock(async () => {
11381138
const {clientID} = this;
11391139
await this.#ready;
11401140
if (this.#closed) {
@@ -1147,7 +1147,7 @@ export class ReplicacheImpl<MD extends MutatorDefs = {}> {
11471147
this.memdag,
11481148
this.perdag,
11491149
this.#mutatorRegistry,
1150-
() => this.closed,
1150+
() => this.#closed,
11511151
FormatVersion.Latest,
11521152
);
11531153
} catch (e) {
@@ -1159,14 +1159,11 @@ export class ReplicacheImpl<MD extends MutatorDefs = {}> {
11591159
throw e;
11601160
}
11611161
}
1162-
} finally {
1163-
this.#persistIsRunning = false;
1164-
}
11651162

1166-
const {clientID} = this;
1167-
const clientGroupID = await this.#clientGroupIDPromise;
1168-
assert(clientGroupID);
1169-
this.#onPersist({clientID, clientGroupID});
1163+
const clientGroupID = await this.#clientGroupIDPromise;
1164+
assert(clientGroupID);
1165+
this.#onPersist({clientID, clientGroupID});
1166+
});
11701167
}
11711168

11721169
async refresh(): Promise<void> {

packages/zero-client/src/client/zero.bench.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import {resolver} from '@rocicorp/resolver';
22
import {bench, describe, expect} from 'vitest';
3-
import {sleep} from '../../../shared/src/sleep.js';
43
import type {Row} from '../../../zql/src/query/query.js';
54
import {getInternalReplicacheImplForTesting, Zero} from './zero.js';
65

@@ -44,7 +43,6 @@ async function withZero(
4443
});
4544
await f(z);
4645
if (persist) {
47-
await sleep(500);
4846
await getInternalReplicacheImplForTesting(z).persist();
4947
}
5048
await z.close();

0 commit comments

Comments
 (0)