@rocicorp/zero 0.25.10-canary.9 → 0.25.11-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/replicache/src/persist/refresh.d.ts.map +1 -1
- package/out/replicache/src/persist/refresh.js +0 -8
- package/out/replicache/src/persist/refresh.js.map +1 -1
- package/out/replicache/src/process-scheduler.d.ts +23 -0
- package/out/replicache/src/process-scheduler.d.ts.map +1 -1
- package/out/replicache/src/process-scheduler.js +50 -1
- package/out/replicache/src/process-scheduler.js.map +1 -1
- package/out/replicache/src/replicache-impl.d.ts +8 -0
- package/out/replicache/src/replicache-impl.d.ts.map +1 -1
- package/out/replicache/src/replicache-impl.js +10 -1
- package/out/replicache/src/replicache-impl.js.map +1 -1
- package/out/zero/package.json.js +1 -1
- package/out/zero-cache/src/custom/fetch.d.ts +3 -3
- package/out/zero-cache/src/custom/fetch.d.ts.map +1 -1
- package/out/zero-cache/src/custom/fetch.js +116 -76
- package/out/zero-cache/src/custom/fetch.js.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.d.ts.map +1 -1
- package/out/zero-cache/src/custom-queries/transform-query.js +0 -1
- package/out/zero-cache/src/custom-queries/transform-query.js.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.d.ts.map +1 -1
- package/out/zero-cache/src/server/anonymous-otel-start.js +1 -0
- package/out/zero-cache/src/server/anonymous-otel-start.js.map +1 -1
- package/out/zero-cache/src/server/change-streamer.d.ts.map +1 -1
- package/out/zero-cache/src/server/change-streamer.js +6 -1
- package/out/zero-cache/src/server/change-streamer.js.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.d.ts.map +1 -1
- package/out/zero-cache/src/server/inspector-delegate.js +2 -2
- package/out/zero-cache/src/server/inspector-delegate.js.map +1 -1
- package/out/zero-cache/src/server/priority-op.d.ts +8 -0
- package/out/zero-cache/src/server/priority-op.d.ts.map +1 -0
- package/out/zero-cache/src/server/priority-op.js +29 -0
- package/out/zero-cache/src/server/priority-op.js.map +1 -0
- package/out/zero-cache/src/server/syncer.d.ts.map +1 -1
- package/out/zero-cache/src/server/syncer.js +9 -2
- package/out/zero-cache/src/server/syncer.js.map +1 -1
- package/out/zero-cache/src/services/analyze.js +1 -1
- package/out/zero-cache/src/services/analyze.js.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js +5 -1
- package/out/zero-cache/src/services/change-source/replica-schema.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.d.ts.map +1 -1
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js +10 -6
- package/out/zero-cache/src/services/change-streamer/backup-monitor.js.map +1 -1
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js +2 -2
- package/out/zero-cache/src/services/change-streamer/change-streamer-http.js.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.d.ts.map +1 -1
- package/out/zero-cache/src/services/mutagen/pusher.js +1 -3
- package/out/zero-cache/src/services/mutagen/pusher.js.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts +2 -1
- package/out/zero-cache/src/services/replicator/replication-status.d.ts.map +1 -1
- package/out/zero-cache/src/services/replicator/replication-status.js +7 -3
- package/out/zero-cache/src/services/replicator/replication-status.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr-store.js +60 -22
- package/out/zero-cache/src/services/view-syncer/cvr-store.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/cvr.js +2 -0
- package/out/zero-cache/src/services/view-syncer/cvr.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js +2 -2
- package/out/zero-cache/src/services/view-syncer/pipeline-driver.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js +22 -11
- package/out/zero-cache/src/services/view-syncer/row-record-cache.js.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts +2 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.d.ts.map +1 -1
- package/out/zero-cache/src/services/view-syncer/view-syncer.js +80 -52
- package/out/zero-cache/src/services/view-syncer/view-syncer.js.map +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts +1 -1
- package/out/zero-cache/src/types/error-with-level.d.ts.map +1 -1
- package/out/zero-cache/src/types/error-with-level.js +1 -1
- package/out/zero-cache/src/types/error-with-level.js.map +1 -1
- package/out/zero-client/src/client/connection-manager.d.ts +3 -0
- package/out/zero-client/src/client/connection-manager.d.ts.map +1 -1
- package/out/zero-client/src/client/connection-manager.js +10 -3
- package/out/zero-client/src/client/connection-manager.js.map +1 -1
- package/out/zero-client/src/client/error.d.ts +5 -1
- package/out/zero-client/src/client/error.d.ts.map +1 -1
- package/out/zero-client/src/client/error.js +3 -3
- package/out/zero-client/src/client/error.js.map +1 -1
- package/out/zero-client/src/client/options.d.ts +1 -1
- package/out/zero-client/src/client/options.js.map +1 -1
- package/out/zero-client/src/client/version.js +1 -1
- package/out/zero-client/src/client/zero.d.ts +2 -1
- package/out/zero-client/src/client/zero.d.ts.map +1 -1
- package/out/zero-client/src/client/zero.js +29 -3
- package/out/zero-client/src/client/zero.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../../../replicache/src/persist/refresh.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAC,KAAK,EAAC,MAAM,iBAAiB,CAAC;AAe3C,OAAO,KAAK,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,YAAY,CAAC;AACrC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAC,KAAK,qBAAqB,EAAc,MAAM,iBAAiB,CAAC;AACxE,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,aAAa,CAAC;AAe7C,KAAK,aAAa,GAAG,IAAI,CAAC,OAAO,aAAa,CAAC,CAAC;AAiBhD;;;GAGG;AACH,wBAAsB,OAAO,CAC3B,EAAE,EAAE,UAAU,EACd,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,EACb,QAAQ,EAAE,QAAQ,EAClB,QAAQ,EAAE,WAAW,EACrB,UAAU,EAAE,qBAAqB,EACjC,MAAM,EAAE,MAAM,OAAO,EACrB,aAAa,EAAE,aAAa,EAC5B,IAAI,EAAE,UAAU,GAAG,SAAS,GAC3B,OAAO,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAAC,GAAG,SAAS,CAAC,CAiOtE"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { sleep } from "../../../shared/src/sleep.js";
|
|
2
1
|
import { assertSnapshotCommitDD31, baseSnapshotFromHead, commitFromHash, baseSnapshotFromHash, commitFromHead, DEFAULT_HEAD_NAME, baseSnapshotFromCommit, localMutationsGreaterThan, compareCookiesForSnapshots } from "../db/commit.js";
|
|
3
2
|
import { rebaseMutationAndPutCommit } from "../db/rebase.js";
|
|
4
3
|
import { diffCommits } from "../sync/diff.js";
|
|
@@ -6,7 +5,6 @@ import { withRead, withWrite } from "../with-transactions.js";
|
|
|
6
5
|
import { getClientGroupForClient, ClientStateNotFoundError, mustGetClient, assertClientV6, setClient } from "./clients.js";
|
|
7
6
|
import { GatherNotCachedVisitor } from "./gather-not-cached-visitor.js";
|
|
8
7
|
const GATHER_SIZE_LIMIT = 5 * 2 ** 20;
|
|
9
|
-
const DELAY_MS = 300;
|
|
10
8
|
async function refresh(lc, memdag, perdag, clientID, mutators, diffConfig, closed, formatVersion, zero) {
|
|
11
9
|
if (closed()) {
|
|
12
10
|
return;
|
|
@@ -78,12 +76,6 @@ async function refresh(lc, memdag, perdag, clientID, mutators, diffConfig, close
|
|
|
78
76
|
type: "aborted"
|
|
79
77
|
};
|
|
80
78
|
}
|
|
81
|
-
await sleep(DELAY_MS);
|
|
82
|
-
if (closed()) {
|
|
83
|
-
return {
|
|
84
|
-
type: "aborted"
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
79
|
const [
|
|
88
80
|
perdagClientGroupHeadHash,
|
|
89
81
|
perdagClientGroupBaseSnapshot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"refresh.js","sources":["../../../../../replicache/src/persist/refresh.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport {sleep} from '../../../shared/src/sleep.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption} from '../replicache-options.ts';\nimport type {DiffsMap} from '../sync/diff.ts';\nimport {type DiffComputationConfig, diffCommits} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\nconst DELAY_MS = 300;\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n oldHead: Hash;\n newHead: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n zero: ZeroOption | undefined,\n): Promise<{oldHead: Hash; newHead: Hash; diffs: DiffsMap} | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n } as const;\n }\n // pull/poke and refresh are racing to see who gets to update\n // the memdag (the one with the newer base snapshot cookie wins)\n // pull/poke updates are preferable so delay refresh slightly to\n // make pull/poke the winner except when pull/pokes are slow.\n // This is especially important for pokes, as refresh winning\n // will result in the next poke's cookie not matching necessitating\n // a disconnect/reconnect.\n await sleep(DELAY_MS);\n if (closed()) {\n return {\n type: 'aborted',\n };\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n if (newMemdagMutations.length > 0) {\n const zeroData = await zero?.getTxData?.(newMemdagHeadHash, {\n openLazyRead: memdagWrite,\n });\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n newMemdagHeadHash = (\n await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n oldHead: memdagHeadCommit.chunk.hash,\n newHead: newMemdagHeadHash,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n } as const;\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n\n // Advance zero here before setting refresh hashes\n // since we must advance before delegating control of the microtask\n // loop.\n zero?.advance(result.oldHead, result.newHead, result.diffs.get('') ?? []);\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return {\n oldHead: result.oldHead,\n newHead: result.newHead,\n diffs: result.diffs,\n };\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n"],"names":["perdagClientGroupHeadHash","perdagLmid","perdagClientGroupBaseSnapshot","gatheredChunks","memdagBaseSnapshot"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"refresh.js","sources":["../../../../../replicache/src/persist/refresh.ts"],"sourcesContent":["import type {LogContext} from '@rocicorp/logger';\nimport type {Enum} from '../../../shared/src/enum.ts';\nimport type {LazyStore} from '../dag/lazy-store.ts';\nimport type {Store} from '../dag/store.ts';\nimport type {Commit} from '../db/commit.ts';\nimport {\n DEFAULT_HEAD_NAME,\n type SnapshotMetaDD31,\n assertSnapshotCommitDD31,\n baseSnapshotFromCommit,\n baseSnapshotFromHash,\n baseSnapshotFromHead,\n commitFromHash,\n commitFromHead,\n compareCookiesForSnapshots,\n localMutationsGreaterThan,\n} from '../db/commit.ts';\nimport {rebaseMutationAndPutCommit} from '../db/rebase.ts';\nimport type * as FormatVersion from '../format-version-enum.ts';\nimport type {Hash} from '../hash.ts';\nimport type {ZeroOption} from '../replicache-options.ts';\nimport type {DiffsMap} from '../sync/diff.ts';\nimport {type DiffComputationConfig, diffCommits} from '../sync/diff.ts';\nimport type {ClientID} from '../sync/ids.ts';\nimport type {MutatorDefs} from '../types.ts';\nimport {withRead, withWrite} from '../with-transactions.ts';\nimport {\n ClientStateNotFoundError,\n type ClientV6,\n assertClientV6,\n getClientGroupForClient,\n mustGetClient,\n setClient,\n} from './clients.ts';\nimport {\n type ChunkWithSize,\n GatherNotCachedVisitor,\n} from './gather-not-cached-visitor.ts';\n\ntype FormatVersion = Enum<typeof FormatVersion>;\n\nconst GATHER_SIZE_LIMIT = 5 * 2 ** 20; // 5 MB\n\ntype RefreshResult =\n | {\n type: 'aborted';\n refreshHashesForRevert?: readonly Hash[] | undefined;\n }\n | {\n type: 'complete';\n diffs: DiffsMap;\n newPerdagClientHeadHash: Hash;\n oldHead: Hash;\n newHead: Hash;\n };\n\n/**\n * This returns the diff between the state of the btree before and after\n * refresh. It returns `undefined` if the refresh was aborted.\n */\nexport async function refresh(\n lc: LogContext,\n memdag: LazyStore,\n perdag: Store,\n clientID: ClientID,\n mutators: MutatorDefs,\n diffConfig: DiffComputationConfig,\n closed: () => boolean,\n formatVersion: FormatVersion,\n zero: ZeroOption | undefined,\n): Promise<{oldHead: Hash; newHead: Hash; diffs: DiffsMap} | undefined> {\n if (closed()) {\n return;\n }\n const memdagBaseSnapshot = await withRead(memdag, memdagRead =>\n baseSnapshotFromHead(DEFAULT_HEAD_NAME, memdagRead),\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n\n type PerdagWriteResult = [\n perdagClientGroupHeadHash: Hash,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagLmid: number,\n gatheredChunks: ReadonlyMap<Hash, ChunkWithSize>,\n refreshHashesForRevert: readonly Hash[],\n ];\n\n // Suspend eviction and deletion of chunks cached by the lazy store\n // to prevent cache misses. If eviction and deletion are not suspended\n // some chunks that are not gathered due to already being cached, may be\n // evicted or deleted by the time the write lock is acquired on the memdag,\n // which can lead to cache misses when performing the rebase and diff.\n // It is important to avoid these cache misses because they often create jank\n // because they block local mutations, pulls and queries on reading from idb.\n // Cache misses can still happen during the rebase and diff, but only\n // if the gather step hits its size limit.\n const result: RefreshResult =\n await memdag.withSuspendedSourceCacheEvictsAndDeletes(async () => {\n const perdagWriteResult: PerdagWriteResult | undefined = await withWrite(\n perdag,\n async perdagWrite => {\n const clientGroup = await getClientGroupForClient(\n clientID,\n perdagWrite,\n );\n if (!clientGroup) {\n throw new ClientStateNotFoundError(clientID);\n }\n\n const perdagClientGroupHeadHash = clientGroup.headHash;\n const perdagClientGroupHeadCommit = await commitFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n const perdagLmid = await perdagClientGroupHeadCommit.getMutationID(\n clientID,\n perdagWrite,\n );\n\n // Need to pull this head into memdag, but can't have it disappear if\n // perdag moves forward while we're rebasing in memdag. Can't change\n // client headHash until our rebase in memdag is complete, because if\n // rebase fails, then nothing is keeping client's chunks alive in\n // perdag.\n const client = await mustGetClient(clientID, perdagWrite);\n assertClientV6(client);\n const perdagClientGroupBaseSnapshot = await baseSnapshotFromHash(\n perdagClientGroupHeadHash,\n perdagWrite,\n );\n assertSnapshotCommitDD31(perdagClientGroupBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return undefined;\n }\n\n // To avoid pulling the entire perdag graph into the memdag\n // the amount of chunk data gathered is limited by size.\n const visitor = new GatherNotCachedVisitor(\n perdagWrite,\n memdag,\n GATHER_SIZE_LIMIT,\n );\n await visitor.visit(perdagClientGroupHeadHash);\n const {gatheredChunks} = visitor;\n\n const refreshHashesSet = new Set(client.refreshHashes);\n refreshHashesSet.add(perdagClientGroupHeadHash);\n\n const newClient: ClientV6 = {\n ...client,\n refreshHashes: [...refreshHashesSet],\n };\n\n await setClient(clientID, newClient, perdagWrite);\n return [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n client.refreshHashes,\n ];\n },\n );\n\n if (closed() || !perdagWriteResult) {\n return {\n type: 'aborted',\n } as const;\n }\n\n const [\n perdagClientGroupHeadHash,\n perdagClientGroupBaseSnapshot,\n perdagLmid,\n gatheredChunks,\n refreshHashesForRevert,\n ] = perdagWriteResult;\n return withWrite(memdag, async memdagWrite => {\n const memdagHeadCommit = await commitFromHead(\n DEFAULT_HEAD_NAME,\n memdagWrite,\n );\n const memdagBaseSnapshot = await baseSnapshotFromCommit(\n memdagHeadCommit,\n memdagWrite,\n );\n assertSnapshotCommitDD31(memdagBaseSnapshot);\n if (\n shouldAbortRefresh(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n perdagClientGroupHeadHash,\n )\n ) {\n return {\n type: 'aborted',\n refreshHashesForRevert,\n };\n }\n\n const newMemdagMutations = await localMutationsGreaterThan(\n memdagHeadCommit,\n {[clientID]: perdagLmid},\n memdagWrite,\n );\n const ps = [];\n for (const {chunk, size} of gatheredChunks.values()) {\n ps.push(memdagWrite.putChunk(chunk, size));\n }\n await Promise.all(ps);\n\n let newMemdagHeadHash = perdagClientGroupHeadHash;\n if (newMemdagMutations.length > 0) {\n const zeroData = await zero?.getTxData?.(newMemdagHeadHash, {\n openLazyRead: memdagWrite,\n });\n for (let i = newMemdagMutations.length - 1; i >= 0; i--) {\n newMemdagHeadHash = (\n await rebaseMutationAndPutCommit(\n newMemdagMutations[i],\n memdagWrite,\n newMemdagHeadHash,\n mutators,\n lc,\n newMemdagMutations[i].meta.clientID,\n formatVersion,\n zeroData,\n )\n ).chunk.hash;\n }\n }\n\n const newMemdagHeadCommit = await commitFromHash(\n newMemdagHeadHash,\n memdagWrite,\n );\n const diffs = await diffCommits(\n memdagHeadCommit,\n newMemdagHeadCommit,\n memdagWrite,\n diffConfig,\n formatVersion,\n );\n\n await memdagWrite.setHead(DEFAULT_HEAD_NAME, newMemdagHeadHash);\n return {\n type: 'complete',\n diffs,\n oldHead: memdagHeadCommit.chunk.hash,\n newHead: newMemdagHeadHash,\n newPerdagClientHeadHash: perdagClientGroupHeadHash,\n } as const;\n });\n });\n\n if (closed()) {\n return;\n }\n\n const setRefreshHashes = (refreshHashes: readonly Hash[]) =>\n withWrite(perdag, async perdagWrite => {\n const client = await mustGetClient(clientID, perdagWrite);\n const newClient = {\n ...client,\n refreshHashes,\n };\n\n // If this cleanup never happens, it's no big deal, some data will stay\n // alive longer but next refresh will fix it.\n await setClient(clientID, newClient, perdagWrite);\n });\n\n if (result.type === 'aborted') {\n if (result.refreshHashesForRevert) {\n await setRefreshHashes(result.refreshHashesForRevert);\n }\n return undefined;\n }\n\n // Advance zero here before setting refresh hashes\n // since we must advance before delegating control of the microtask\n // loop.\n zero?.advance(result.oldHead, result.newHead, result.diffs.get('') ?? []);\n await setRefreshHashes([result.newPerdagClientHeadHash]);\n return {\n oldHead: result.oldHead,\n newHead: result.newHead,\n diffs: result.diffs,\n };\n}\n\nfunction shouldAbortRefresh(\n memdagBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupBaseSnapshot: Commit<SnapshotMetaDD31>,\n perdagClientGroupHeadHash: Hash,\n): boolean {\n const baseSnapshotCookieCompareResult = compareCookiesForSnapshots(\n memdagBaseSnapshot,\n perdagClientGroupBaseSnapshot,\n );\n return (\n baseSnapshotCookieCompareResult > 0 ||\n (baseSnapshotCookieCompareResult === 0 &&\n perdagClientGroupHeadHash === perdagClientGroupBaseSnapshot.chunk.hash)\n );\n}\n"],"names":["perdagClientGroupHeadHash","perdagLmid","perdagClientGroupBaseSnapshot","gatheredChunks","memdagBaseSnapshot"],"mappings":"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"}
|
|
@@ -15,6 +15,29 @@ export declare class ProcessScheduler {
|
|
|
15
15
|
* will reject with an `AbortError`.
|
|
16
16
|
*/
|
|
17
17
|
constructor(process: () => Promise<void>, idleTimeoutMs: number, throttleMs: number, abortSignal: AbortSignal, requestIdle?: typeof defaultRequestIdle);
|
|
18
|
+
/**
|
|
19
|
+
* Schedules the process to run.
|
|
20
|
+
*
|
|
21
|
+
* The returned promise resolves when the process has completed running.
|
|
22
|
+
* If the process throws an error, the returned promise rejects with that error.
|
|
23
|
+
*
|
|
24
|
+
* If `schedule()` is called multiple times while a process is running/scheduled,
|
|
25
|
+
* they will be debounced into a single run.
|
|
26
|
+
*/
|
|
18
27
|
schedule(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Runs the process immediately, skipping throttle and idle checks.
|
|
30
|
+
*
|
|
31
|
+
* The returned promise resolves when the process has completed running.
|
|
32
|
+
* If the process throws an error, the returned promise rejects with that error.
|
|
33
|
+
*
|
|
34
|
+
* If there is a scheduled run pending (waiting for idle or throttle), this run
|
|
35
|
+
* will effectively "take over" that scheduled run, and the promise returned
|
|
36
|
+
* by `schedule()` will resolve when this run completes.
|
|
37
|
+
*
|
|
38
|
+
* If there is a process currently running, this run will wait for it to finish
|
|
39
|
+
* before starting, satisfying the non-concurrency constraint.
|
|
40
|
+
*/
|
|
41
|
+
run(): Promise<void>;
|
|
19
42
|
}
|
|
20
43
|
//# sourceMappingURL=process-scheduler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-scheduler.d.ts","sourceRoot":"","sources":["../../../../replicache/src/process-scheduler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,WAAW,IAAI,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAEpE,qBAAa,gBAAgB;;
|
|
1
|
+
{"version":3,"file":"process-scheduler.d.ts","sourceRoot":"","sources":["../../../../replicache/src/process-scheduler.ts"],"names":[],"mappings":"AAIA,OAAO,EAAC,WAAW,IAAI,kBAAkB,EAAC,MAAM,mBAAmB,CAAC;AAEpE,qBAAa,gBAAgB;;IAY3B;;;;;;;;;;;;OAYG;gBAED,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,EAC5B,aAAa,EAAE,MAAM,EACrB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,WAAW,EACxB,WAAW,4BAAqB;IAoBlC;;;;;;;;OAQG;IACH,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAYzB;;;;;;;;;;;;OAYG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAuE3B"}
|
|
@@ -11,7 +11,6 @@ class ProcessScheduler {
|
|
|
11
11
|
#requestIdle;
|
|
12
12
|
#scheduledResolver = void 0;
|
|
13
13
|
#runResolver = void 0;
|
|
14
|
-
// oxlint-disable-next-line no-unused-private-class-members -- False positive, this is used in #run
|
|
15
14
|
#runPromise = Promise.resolve();
|
|
16
15
|
// oxlint-disable-next-line no-unused-private-class-members -- False positive, this is used in #run
|
|
17
16
|
#throttlePromise = Promise.resolve();
|
|
@@ -46,6 +45,15 @@ class ProcessScheduler {
|
|
|
46
45
|
{ once: true }
|
|
47
46
|
);
|
|
48
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Schedules the process to run.
|
|
50
|
+
*
|
|
51
|
+
* The returned promise resolves when the process has completed running.
|
|
52
|
+
* If the process throws an error, the returned promise rejects with that error.
|
|
53
|
+
*
|
|
54
|
+
* If `schedule()` is called multiple times while a process is running/scheduled,
|
|
55
|
+
* they will be debounced into a single run.
|
|
56
|
+
*/
|
|
49
57
|
schedule() {
|
|
50
58
|
if (this.#abortSignal.aborted) {
|
|
51
59
|
return Promise.reject(new AbortError("Aborted"));
|
|
@@ -57,6 +65,47 @@ class ProcessScheduler {
|
|
|
57
65
|
void this.#scheduleInternal();
|
|
58
66
|
return this.#scheduledResolver.promise;
|
|
59
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Runs the process immediately, skipping throttle and idle checks.
|
|
70
|
+
*
|
|
71
|
+
* The returned promise resolves when the process has completed running.
|
|
72
|
+
* If the process throws an error, the returned promise rejects with that error.
|
|
73
|
+
*
|
|
74
|
+
* If there is a scheduled run pending (waiting for idle or throttle), this run
|
|
75
|
+
* will effectively "take over" that scheduled run, and the promise returned
|
|
76
|
+
* by `schedule()` will resolve when this run completes.
|
|
77
|
+
*
|
|
78
|
+
* If there is a process currently running, this run will wait for it to finish
|
|
79
|
+
* before starting, satisfying the non-concurrency constraint.
|
|
80
|
+
*/
|
|
81
|
+
async run() {
|
|
82
|
+
if (this.#abortSignal.aborted) {
|
|
83
|
+
return Promise.reject(new AbortError("Aborted"));
|
|
84
|
+
}
|
|
85
|
+
const resolverToResolve = this.#scheduledResolver;
|
|
86
|
+
this.#scheduledResolver = void 0;
|
|
87
|
+
const prevRunPromise = this.#runPromise;
|
|
88
|
+
const runTask = async () => {
|
|
89
|
+
try {
|
|
90
|
+
await prevRunPromise;
|
|
91
|
+
} catch {
|
|
92
|
+
}
|
|
93
|
+
if (this.#abortSignal.aborted) {
|
|
94
|
+
throw new AbortError("Aborted");
|
|
95
|
+
}
|
|
96
|
+
return this.#process();
|
|
97
|
+
};
|
|
98
|
+
const executionPromise = runTask();
|
|
99
|
+
this.#runPromise = executionPromise;
|
|
100
|
+
this.#throttlePromise = throttle(this.#throttleMs, this.#abortSignal);
|
|
101
|
+
try {
|
|
102
|
+
await executionPromise;
|
|
103
|
+
resolverToResolve?.resolve();
|
|
104
|
+
} catch (e) {
|
|
105
|
+
resolverToResolve?.reject(e);
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
60
109
|
async #scheduleInternal() {
|
|
61
110
|
try {
|
|
62
111
|
await this.#runPromise;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-scheduler.js","sources":["../../../../replicache/src/process-scheduler.ts"],"sourcesContent":["import {type Resolver, resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\nimport {requestIdle as defaultRequestIdle} from './request-idle.ts';\n\nexport class ProcessScheduler {\n readonly #process: () => Promise<void>;\n readonly #idleTimeoutMs: number;\n readonly #throttleMs: number;\n readonly #abortSignal: AbortSignal;\n readonly #requestIdle: typeof defaultRequestIdle;\n #scheduledResolver: Resolver<void> | undefined = undefined;\n #runResolver: Resolver<void> | undefined = undefined;\n
|
|
1
|
+
{"version":3,"file":"process-scheduler.js","sources":["../../../../replicache/src/process-scheduler.ts"],"sourcesContent":["import {type Resolver, resolver} from '@rocicorp/resolver';\nimport {AbortError} from '../../shared/src/abort-error.ts';\nimport {assert} from '../../shared/src/asserts.ts';\nimport {sleep} from '../../shared/src/sleep.ts';\nimport {requestIdle as defaultRequestIdle} from './request-idle.ts';\n\nexport class ProcessScheduler {\n readonly #process: () => Promise<void>;\n readonly #idleTimeoutMs: number;\n readonly #throttleMs: number;\n readonly #abortSignal: AbortSignal;\n readonly #requestIdle: typeof defaultRequestIdle;\n #scheduledResolver: Resolver<void> | undefined = undefined;\n #runResolver: Resolver<void> | undefined = undefined;\n #runPromise = Promise.resolve();\n // oxlint-disable-next-line no-unused-private-class-members -- False positive, this is used in #run\n #throttlePromise = Promise.resolve();\n\n /**\n * Supports scheduling a `process` to be run with certain constraints.\n * - Process runs are never concurrent.\n * - Multiple calls to schedule will be fulfilled by a single process\n * run started after the call to schedule. A call is never fulfilled by an\n * already running process run. This can be thought of as debouncing.\n * - Process runs are throttled so that the process runs at most once every\n * `throttleMs`.\n * - Process runs try to run during an idle period, but will delay at most\n * `idleTimeoutMs`.\n * - Scheduled runs which have not completed when `abortSignal` is aborted\n * will reject with an `AbortError`.\n */\n constructor(\n process: () => Promise<void>,\n idleTimeoutMs: number,\n throttleMs: number,\n abortSignal: AbortSignal,\n requestIdle = defaultRequestIdle,\n ) {\n this.#process = process;\n this.#idleTimeoutMs = idleTimeoutMs;\n this.#throttleMs = throttleMs;\n this.#abortSignal = abortSignal;\n this.#requestIdle = requestIdle;\n this.#abortSignal.addEventListener(\n 'abort',\n () => {\n const abortError = new AbortError('Aborted');\n this.#runResolver?.reject(abortError);\n this.#scheduledResolver?.reject(abortError);\n this.#runResolver = undefined;\n this.#scheduledResolver = undefined;\n },\n {once: true},\n );\n }\n\n /**\n * Schedules the process to run.\n *\n * The returned promise resolves when the process has completed running.\n * If the process throws an error, the returned promise rejects with that error.\n *\n * If `schedule()` is called multiple times while a process is running/scheduled,\n * they will be debounced into a single run.\n */\n schedule(): Promise<void> {\n if (this.#abortSignal.aborted) {\n return Promise.reject(new AbortError('Aborted'));\n }\n if (this.#scheduledResolver) {\n return this.#scheduledResolver.promise;\n }\n this.#scheduledResolver = resolver();\n void this.#scheduleInternal();\n return this.#scheduledResolver.promise;\n }\n\n /**\n * Runs the process immediately, skipping throttle and idle checks.\n *\n * The returned promise resolves when the process has completed running.\n * If the process throws an error, the returned promise rejects with that error.\n *\n * If there is a scheduled run pending (waiting for idle or throttle), this run\n * will effectively \"take over\" that scheduled run, and the promise returned\n * by `schedule()` will resolve when this run completes.\n *\n * If there is a process currently running, this run will wait for it to finish\n * before starting, satisfying the non-concurrency constraint.\n */\n async run(): Promise<void> {\n if (this.#abortSignal.aborted) {\n return Promise.reject(new AbortError('Aborted'));\n }\n\n // \"Steal\" the scheduled resolver if it exists.\n // This effectively cancels the pending scheduled run (the idle/throttle wait),\n // and fulfills that promise with this run.\n const resolverToResolve = this.#scheduledResolver;\n this.#scheduledResolver = undefined;\n\n // Wait for any currently running process to finish.\n // We create a new promise that represents \"Wait for current, then run me\"\n const prevRunPromise = this.#runPromise;\n\n const runTask = async () => {\n try {\n await prevRunPromise;\n } catch {\n // ignore errors from previous run\n }\n\n if (this.#abortSignal.aborted) {\n throw new AbortError('Aborted');\n }\n\n return this.#process();\n };\n\n const executionPromise = runTask();\n this.#runPromise = executionPromise;\n\n // Reset throttle promise so future runs respect the throttle relative to this run.\n this.#throttlePromise = throttle(this.#throttleMs, this.#abortSignal);\n\n try {\n await executionPromise;\n resolverToResolve?.resolve();\n } catch (e) {\n resolverToResolve?.reject(e);\n throw e;\n }\n }\n\n async #scheduleInternal(): Promise<void> {\n try {\n await this.#runPromise;\n // Prevent errors thrown by process from cancelling scheduled runs.\n // this._runPromise is also awaited below and errors are explicitly\n // propagated to promises returned from schedule.\n } catch {}\n await this.#throttlePromise;\n if (!this.#scheduledResolver) {\n return;\n }\n await this.#requestIdle(this.#idleTimeoutMs);\n if (!this.#scheduledResolver) {\n return;\n }\n this.#throttlePromise = throttle(this.#throttleMs, this.#abortSignal);\n this.#runResolver = this.#scheduledResolver;\n this.#scheduledResolver = undefined;\n try {\n this.#runPromise = this.#process();\n await this.#runPromise;\n this.#runResolver?.resolve();\n } catch (e) {\n this.#runResolver?.reject(e);\n }\n this.#runResolver = undefined;\n }\n}\n\nasync function throttle(\n timeMs: number,\n abortSignal: AbortSignal,\n): Promise<void> {\n try {\n await sleep(timeMs, abortSignal);\n } catch (e) {\n assert(e instanceof AbortError);\n }\n}\n"],"names":["requestIdle","defaultRequestIdle"],"mappings":";;;;;AAMO,MAAM,iBAAiB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACT,qBAAiD;AAAA,EACjD,eAA2C;AAAA,EAC3C,cAAc,QAAQ,QAAA;AAAA;AAAA,EAEtB,mBAAmB,QAAQ,QAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe3B,YACE,SACA,eACA,YACA,aACAA,gBAAcC,aACd;AACA,SAAK,WAAW;AAChB,SAAK,iBAAiB;AACtB,SAAK,cAAc;AACnB,SAAK,eAAe;AACpB,SAAK,eAAeD;AACpB,SAAK,aAAa;AAAA,MAChB;AAAA,MACA,MAAM;AACJ,cAAM,aAAa,IAAI,WAAW,SAAS;AAC3C,aAAK,cAAc,OAAO,UAAU;AACpC,aAAK,oBAAoB,OAAO,UAAU;AAC1C,aAAK,eAAe;AACpB,aAAK,qBAAqB;AAAA,MAC5B;AAAA,MACA,EAAC,MAAM,KAAA;AAAA,IAAI;AAAA,EAEf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,WAA0B;AACxB,QAAI,KAAK,aAAa,SAAS;AAC7B,aAAO,QAAQ,OAAO,IAAI,WAAW,SAAS,CAAC;AAAA,IACjD;AACA,QAAI,KAAK,oBAAoB;AAC3B,aAAO,KAAK,mBAAmB;AAAA,IACjC;AACA,SAAK,qBAAqB,SAAA;AAC1B,SAAK,KAAK,kBAAA;AACV,WAAO,KAAK,mBAAmB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,MAAM,MAAqB;AACzB,QAAI,KAAK,aAAa,SAAS;AAC7B,aAAO,QAAQ,OAAO,IAAI,WAAW,SAAS,CAAC;AAAA,IACjD;AAKA,UAAM,oBAAoB,KAAK;AAC/B,SAAK,qBAAqB;AAI1B,UAAM,iBAAiB,KAAK;AAE5B,UAAM,UAAU,YAAY;AAC1B,UAAI;AACF,cAAM;AAAA,MACR,QAAQ;AAAA,MAER;AAEA,UAAI,KAAK,aAAa,SAAS;AAC7B,cAAM,IAAI,WAAW,SAAS;AAAA,MAChC;AAEA,aAAO,KAAK,SAAA;AAAA,IACd;AAEA,UAAM,mBAAmB,QAAA;AACzB,SAAK,cAAc;AAGnB,SAAK,mBAAmB,SAAS,KAAK,aAAa,KAAK,YAAY;AAEpE,QAAI;AACF,YAAM;AACN,yBAAmB,QAAA;AAAA,IACrB,SAAS,GAAG;AACV,yBAAmB,OAAO,CAAC;AAC3B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,oBAAmC;AACvC,QAAI;AACF,YAAM,KAAK;AAAA,IAIb,QAAQ;AAAA,IAAC;AACT,UAAM,KAAK;AACX,QAAI,CAAC,KAAK,oBAAoB;AAC5B;AAAA,IACF;AACA,UAAM,KAAK,aAAa,KAAK,cAAc;AAC3C,QAAI,CAAC,KAAK,oBAAoB;AAC5B;AAAA,IACF;AACA,SAAK,mBAAmB,SAAS,KAAK,aAAa,KAAK,YAAY;AACpE,SAAK,eAAe,KAAK;AACzB,SAAK,qBAAqB;AAC1B,QAAI;AACF,WAAK,cAAc,KAAK,SAAA;AACxB,YAAM,KAAK;AACX,WAAK,cAAc,QAAA;AAAA,IACrB,SAAS,GAAG;AACV,WAAK,cAAc,OAAO,CAAC;AAAA,IAC7B;AACA,SAAK,eAAe;AAAA,EACtB;AACF;AAEA,eAAe,SACb,QACA,aACe;AACf,MAAI;AACF,UAAM,MAAM,QAAQ,WAAW;AAAA,EACjC,SAAS,GAAG;AACV,WAAO,aAAa,UAAU;AAAA,EAChC;AACF;"}
|
|
@@ -29,6 +29,10 @@ export interface ReplicacheImplOptions {
|
|
|
29
29
|
* Defaults to true.
|
|
30
30
|
*/
|
|
31
31
|
enableScheduledRefresh?: boolean | undefined;
|
|
32
|
+
/**
|
|
33
|
+
* Defaults to `() => true`.
|
|
34
|
+
*/
|
|
35
|
+
enableRefresh?: (() => boolean) | undefined;
|
|
32
36
|
/**
|
|
33
37
|
* Defaults to true.
|
|
34
38
|
*/
|
|
@@ -257,6 +261,10 @@ export declare class ReplicacheImpl<MD extends MutatorDefs = {}> {
|
|
|
257
261
|
persist(): Promise<void>;
|
|
258
262
|
refresh(): Promise<void>;
|
|
259
263
|
disableClientGroup(): Promise<void>;
|
|
264
|
+
/**
|
|
265
|
+
* Runs a refresh as soon as possible through the refresh scheduler.
|
|
266
|
+
*/
|
|
267
|
+
runRefresh(): Promise<void>;
|
|
260
268
|
/**
|
|
261
269
|
* Subscribe to the result of a {@link query}. The `body` function is
|
|
262
270
|
* evaluated once and its results are returned via `onData`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"replicache-impl.d.ts","sourceRoot":"","sources":["../../../../replicache/src/replicache-impl.ts"],"names":[],"mappings":"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"}
|
|
@@ -155,6 +155,7 @@ class ReplicacheImpl {
|
|
|
155
155
|
#persistLock = new Lock();
|
|
156
156
|
#enableScheduledPersist;
|
|
157
157
|
#enableScheduledRefresh;
|
|
158
|
+
#enableRefresh;
|
|
158
159
|
#enablePullAndPushInOpen;
|
|
159
160
|
#persistScheduler = new ProcessScheduler(
|
|
160
161
|
() => this.persist(),
|
|
@@ -255,6 +256,7 @@ class ReplicacheImpl {
|
|
|
255
256
|
enableMutationRecovery = true,
|
|
256
257
|
enableScheduledPersist = true,
|
|
257
258
|
enableScheduledRefresh = true,
|
|
259
|
+
enableRefresh = () => true,
|
|
258
260
|
enablePullAndPushInOpen = true,
|
|
259
261
|
enableClientGroupForking = true,
|
|
260
262
|
onClientsDeleted = () => promiseVoid
|
|
@@ -271,6 +273,7 @@ class ReplicacheImpl {
|
|
|
271
273
|
this.pusher = pusher ?? getDefaultPusher(this);
|
|
272
274
|
this.#enableScheduledPersist = enableScheduledPersist;
|
|
273
275
|
this.#enableScheduledRefresh = enableScheduledRefresh;
|
|
276
|
+
this.#enableRefresh = enableRefresh;
|
|
274
277
|
this.#enablePullAndPushInOpen = enablePullAndPushInOpen;
|
|
275
278
|
this.#lc = createLogContext(logLevel, logSinks, { name });
|
|
276
279
|
this.#lc.debug?.("Constructing Replicache", {
|
|
@@ -869,7 +872,7 @@ class ReplicacheImpl {
|
|
|
869
872
|
async refresh() {
|
|
870
873
|
await this.#ready;
|
|
871
874
|
const { clientID } = this;
|
|
872
|
-
if (this.#closed) {
|
|
875
|
+
if (this.#closed || !this.#enableRefresh()) {
|
|
873
876
|
return;
|
|
874
877
|
}
|
|
875
878
|
let refreshResult;
|
|
@@ -956,6 +959,12 @@ class ReplicacheImpl {
|
|
|
956
959
|
}
|
|
957
960
|
}
|
|
958
961
|
}
|
|
962
|
+
/**
|
|
963
|
+
* Runs a refresh as soon as possible through the refresh scheduler.
|
|
964
|
+
*/
|
|
965
|
+
runRefresh() {
|
|
966
|
+
return this.#refreshScheduler.run();
|
|
967
|
+
}
|
|
959
968
|
#changeSyncCounters(pushDelta, pullDelta) {
|
|
960
969
|
this.#pushCounter += pushDelta;
|
|
961
970
|
this.#pullCounter += pullDelta;
|