@agoric/swing-store 0.9.2-dev-7bfadd3.0 → 0.9.2-dev-f2445bc.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/docs/data-export.md +20 -11
- package/package.json +4 -4
- package/src/assertComplete.js +5 -6
- package/src/bundleStore.js +4 -3
- package/src/exporter.js +18 -12
- package/src/importer.js +17 -13
- package/src/internal.js +10 -2
- package/src/repairMetadata.js +3 -1
- package/src/snapStore.js +11 -10
- package/src/transcriptStore.js +122 -57
- package/src/types.d.ts +10 -9
- package/test/test-export.js +78 -43
- package/test/test-exportImport.js +57 -16
- package/test/test-import.js +76 -47
- package/test/test-repair-metadata.js +10 -10
package/docs/data-export.md
CHANGED
|
@@ -179,22 +179,31 @@ As a result, for each active vat, the first-stage Export Data contains a record
|
|
|
179
179
|
|
|
180
180
|
The `openSwingStore()` function has an option named `keepTranscripts` (which defaults to `true`), which causes the transcriptStore to retain the old transcript items. A second option named `keepSnapshots` (which defaults to `false`) causes the snapStore to retain the old heap snapshots. Opening the swingStore with a `false` option does not necessarily delete the old items immediately, but they'll probably get deleted the next time the kernel triggers a heap snapshot or transcript-span rollover. Validators who care about minimizing their disk usage will want to set both to `false`. In the future, we will arrange the SwingStore SQLite tables to provide easy `sqlite3` CLI commands that will delete the old data, so validators can also periodically use the CLI command to prune it.
|
|
181
181
|
|
|
182
|
-
When exporting, the `makeSwingStoreExporter()` function takes an `
|
|
183
|
-
* `current`: include only the current transcript span and current snapshot for each vat: just the minimum set necessary for current operations
|
|
184
|
-
* `archival`: include all available transcript spans
|
|
185
|
-
* `debug`: include all available transcript spans *and* all available snapshots. The old snapshots are never necessary for normal operations, nor are they likely to be usefor for extreme upgrade scenarios, but they might be useful for some unusual debugging operation
|
|
182
|
+
When exporting, the `makeSwingStoreExporter()` function takes an `artifactMode` option (in an options bag). This serves to both limit, and provide some minimal guarantees about, the set of artifacts that will be provided in the export. The defined values of `artifactMode` each build upon the previous one:
|
|
186
183
|
|
|
187
|
-
|
|
184
|
+
* `operational`: include only the current transcript span and current snapshot for each vat: just the minimum set necessary for current operations
|
|
185
|
+
* `replay`: add all transcript spans for the current incarnation
|
|
186
|
+
* `archival`: add all available transcript spans, even for old incarnations
|
|
187
|
+
* `debug`: add all available snapshots, giving you everything. The old snapshots are never necessary for normal operations, nor are they likely to be useful for extreme upgrade scenarios, but they might be useful for some unusual debugging operations or investigations
|
|
188
188
|
|
|
189
|
-
|
|
189
|
+
For each mode, the export will fail if the data necessary for those artifacts is not available (e.g. it was previously pruned). For example, an export with `artifactMode: 'replay'` will fail unless every vat has all transcript entries for each one's current incarnation. The `archival` mode will fail to export unless every vat has *every* transcript entry, back to the very first incarnation.
|
|
190
190
|
|
|
191
|
-
|
|
191
|
+
However the `debug` export mode will never fail: it merely dumps everything in the swingstore, without limits or completeness checks.
|
|
192
192
|
|
|
193
|
-
|
|
193
|
+
Note that `artifactMode` does not affect the Export Data generated by the exporter (because if we *ever* want to validate this optional data, the hashes are mandatory). It only affects the names returned by `getArtifactNames()`: `operational` returns a subset of `replay`, which returns a subset of `archival`. And re-exporting from a previously-pruned copy under `archival` mode will fail, because the second SwingStore cannot magically reconstruct the missing data.
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
Also note that when a vat is terminated, we delete all information about it, including transcript items and snapshots, both current and old. This will remove all the Export Data records, and well as the matching artifacts from `getArtifactNames`.
|
|
196
|
+
|
|
197
|
+
When importing, the `importSwingStore()` function's options bag takes a property named `artifactMode`, with the same meanings as for export. Importing with the `operational` mode will ignore any artifacts other than those needed for current operations, and will fail unless all such artifacts were available. Importing with `replay` will ignore spans from old incarnations, but will fail unless all spans from current incarnations are present. Importing with `archival` will fail unless all spans from all incarnations are present. There is no `debug` option during import.
|
|
198
|
+
|
|
199
|
+
`importSwingStore()` returns a swingstore, which means its options bag also contains the same options as `openSwingStore()`, including the `keepTranscripts` option. This defaults to `true`, but if it were overridden to `false`, then the new swingstore will delete transcript spans as soon as they are no longer needed for operational purposes (e.g. when `transcriptStore.rolloverSpan()` is called).
|
|
200
|
+
|
|
201
|
+
So, to avoid pruning current-incarnation historical transcript spans when exporting from one swingstore to another, you must set (or avoid overriding) the following options along the way:
|
|
202
|
+
|
|
203
|
+
* the original swingstore must not be opened with `{ keepTranscripts: false }`, otherwise the old spans will be pruned immediately
|
|
204
|
+
* the export must use `makeSwingStoreExporter(dirpath, { artifactMode: 'replay'})`, otherwise the export will omit the old spans
|
|
205
|
+
* the import must use `importSwingStore(exporter, dirPath, { artifactMode: 'replay'})`, otherwise the import will ignore the old spans
|
|
206
|
+
* the `importSwingStore` call (and all subsequent `openSwingStore` calls) must not use `keepTranscripts: false`, otherwise the new swingstore will prune historical spans as new ones are created (during `rolloverSpan`).
|
|
198
207
|
|
|
199
208
|
## Implementation Details
|
|
200
209
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/swing-store",
|
|
3
|
-
"version": "0.9.2-dev-
|
|
3
|
+
"version": "0.9.2-dev-f2445bc.0+f2445bc",
|
|
4
4
|
"description": "Persistent storage for SwingSet",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
"lint:eslint": "eslint ."
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@agoric/assert": "0.6.1-dev-
|
|
25
|
-
"@agoric/internal": "0.3.3-dev-
|
|
24
|
+
"@agoric/assert": "0.6.1-dev-f2445bc.0+f2445bc",
|
|
25
|
+
"@agoric/internal": "0.3.3-dev-f2445bc.0+f2445bc",
|
|
26
26
|
"@endo/base64": "^0.2.32",
|
|
27
27
|
"@endo/bundle-source": "^2.5.2",
|
|
28
28
|
"@endo/check-bundle": "^0.2.19",
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
],
|
|
46
46
|
"timeout": "2m"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "f2445bcb471c26169ea8052d04e96d51ef9f1487"
|
|
49
49
|
}
|
package/src/assertComplete.js
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @param {import('./internal.js').SwingStoreInternal} internal
|
|
3
|
-
* @param {'
|
|
3
|
+
* @param {Omit<import('./internal.js').ArtifactMode, 'debug'>} checkMode
|
|
4
4
|
* @returns {void}
|
|
5
5
|
*/
|
|
6
|
-
export function assertComplete(internal,
|
|
7
|
-
assert.equal(level, 'operational'); // only option for now
|
|
6
|
+
export function assertComplete(internal, checkMode) {
|
|
8
7
|
// every bundle must be populated
|
|
9
|
-
internal.bundleStore.assertComplete(
|
|
8
|
+
internal.bundleStore.assertComplete(checkMode);
|
|
10
9
|
|
|
11
10
|
// every 'isCurrent' transcript span must have all items
|
|
12
11
|
// TODO: every vat with any data must have a isCurrent transcript
|
|
13
12
|
// span
|
|
14
|
-
internal.transcriptStore.assertComplete(
|
|
13
|
+
internal.transcriptStore.assertComplete(checkMode);
|
|
15
14
|
|
|
16
15
|
// every 'inUse' snapshot must be populated
|
|
17
|
-
internal.snapStore.assertComplete(
|
|
16
|
+
internal.snapStore.assertComplete(checkMode);
|
|
18
17
|
|
|
19
18
|
// TODO: every isCurrent span that starts with load-snapshot has a
|
|
20
19
|
// matching snapshot (counter-argument: swing-store should not know
|
package/src/bundleStore.js
CHANGED
|
@@ -16,6 +16,7 @@ import { createSHA256 } from './hasher.js';
|
|
|
16
16
|
*/
|
|
17
17
|
/**
|
|
18
18
|
* @typedef { import('./exporter').SwingStoreExporter } SwingStoreExporter
|
|
19
|
+
* @typedef { import('./internal.js').ArtifactMode } ArtifactMode
|
|
19
20
|
*
|
|
20
21
|
* @typedef {{
|
|
21
22
|
* addBundle: (bundleID: string, bundle: Bundle) => void;
|
|
@@ -29,7 +30,7 @@ import { createSHA256 } from './hasher.js';
|
|
|
29
30
|
* repairBundleRecord: (key: string, value: string) => void,
|
|
30
31
|
* importBundleRecord: (key: string, value: string) => void,
|
|
31
32
|
* importBundle: (name: string, dataProvider: () => Promise<Buffer>) => Promise<void>,
|
|
32
|
-
* assertComplete: (
|
|
33
|
+
* assertComplete: (checkMode: Omit<ArtifactMode, 'debug'>) => void,
|
|
33
34
|
* getExportRecords: () => IterableIterator<readonly [key: string, value: string]>,
|
|
34
35
|
* getArtifactNames: () => AsyncIterableIterator<string>,
|
|
35
36
|
* getBundleIDs: () => IterableIterator<string>,
|
|
@@ -162,8 +163,8 @@ export function makeBundleStore(db, ensureTxn, noteExport = () => {}) {
|
|
|
162
163
|
return sqlGetPrunedBundles.all();
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
function assertComplete(
|
|
166
|
-
assert
|
|
166
|
+
function assertComplete(checkMode) {
|
|
167
|
+
assert(checkMode !== 'debug', checkMode);
|
|
167
168
|
const pruned = getPrunedBundles();
|
|
168
169
|
if (pruned.length) {
|
|
169
170
|
throw Fail`missing bundles for: ${pruned.join(',')}`;
|
package/src/exporter.js
CHANGED
|
@@ -8,6 +8,8 @@ import { makeBundleStore } from './bundleStore.js';
|
|
|
8
8
|
import { makeSnapStore } from './snapStore.js';
|
|
9
9
|
import { makeSnapStoreIO } from './snapStoreIO.js';
|
|
10
10
|
import { makeTranscriptStore } from './transcriptStore.js';
|
|
11
|
+
import { assertComplete } from './assertComplete.js';
|
|
12
|
+
import { validateArtifactMode } from './internal.js';
|
|
11
13
|
|
|
12
14
|
/**
|
|
13
15
|
* @template T
|
|
@@ -53,7 +55,7 @@ import { makeTranscriptStore } from './transcriptStore.js';
|
|
|
53
55
|
*
|
|
54
56
|
* Get a list of name of artifacts available from the swingStore. A name
|
|
55
57
|
* returned by this method guarantees that a call to `getArtifact` on the same
|
|
56
|
-
* exporter instance will succeed. The `
|
|
58
|
+
* exporter instance will succeed. The `artifactMode` option to
|
|
57
59
|
* `makeSwingStoreExporter` controls the filtering of the artifact names
|
|
58
60
|
* yielded.
|
|
59
61
|
*
|
|
@@ -75,22 +77,20 @@ import { makeTranscriptStore } from './transcriptStore.js';
|
|
|
75
77
|
*/
|
|
76
78
|
|
|
77
79
|
/**
|
|
78
|
-
* @typedef {
|
|
80
|
+
* @typedef { object } ExportSwingStoreOptions
|
|
81
|
+
* @property { import('./internal.js').ArtifactMode } [artifactMode] What artifacts should/must the exporter provide?
|
|
79
82
|
*/
|
|
80
83
|
|
|
81
84
|
/**
|
|
82
85
|
* @param {string} dirPath
|
|
83
|
-
* @param {
|
|
86
|
+
* @param { ExportSwingStoreOptions } [options]
|
|
84
87
|
* @returns {SwingStoreExporter}
|
|
85
88
|
*/
|
|
86
|
-
export function makeSwingStoreExporter(dirPath,
|
|
89
|
+
export function makeSwingStoreExporter(dirPath, options = {}) {
|
|
87
90
|
typeof dirPath === 'string' || Fail`dirPath must be a string`;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Fail`invalid exportMode ${q(exportMode)}`;
|
|
92
|
-
const exportHistoricalSnapshots = exportMode === 'debug';
|
|
93
|
-
const exportHistoricalTranscripts = exportMode !== 'current';
|
|
91
|
+
const { artifactMode = 'operational' } = options;
|
|
92
|
+
validateArtifactMode(artifactMode);
|
|
93
|
+
|
|
94
94
|
const filePath = dbFileInDirectory(dirPath);
|
|
95
95
|
const db = sqlite3(filePath);
|
|
96
96
|
|
|
@@ -106,6 +106,12 @@ export function makeSwingStoreExporter(dirPath, exportMode = 'current') {
|
|
|
106
106
|
const bundleStore = makeBundleStore(db, ensureTxn);
|
|
107
107
|
const transcriptStore = makeTranscriptStore(db, ensureTxn, () => {});
|
|
108
108
|
|
|
109
|
+
if (artifactMode !== 'debug') {
|
|
110
|
+
// throw early if this DB will not be able to create all the desired artifacts
|
|
111
|
+
const internal = { snapStore, bundleStore, transcriptStore };
|
|
112
|
+
assertComplete(internal, artifactMode);
|
|
113
|
+
}
|
|
114
|
+
|
|
109
115
|
const sqlGetAllKVData = db.prepare(`
|
|
110
116
|
SELECT key, value
|
|
111
117
|
FROM kvStore
|
|
@@ -132,8 +138,8 @@ export function makeSwingStoreExporter(dirPath, exportMode = 'current') {
|
|
|
132
138
|
* @yields {string}
|
|
133
139
|
*/
|
|
134
140
|
async function* getArtifactNames() {
|
|
135
|
-
yield* snapStore.getArtifactNames(
|
|
136
|
-
yield* transcriptStore.getArtifactNames(
|
|
141
|
+
yield* snapStore.getArtifactNames(artifactMode);
|
|
142
|
+
yield* transcriptStore.getArtifactNames(artifactMode);
|
|
137
143
|
yield* bundleStore.getArtifactNames();
|
|
138
144
|
}
|
|
139
145
|
|
package/src/importer.js
CHANGED
|
@@ -2,11 +2,12 @@ import { Fail, q } from '@agoric/assert';
|
|
|
2
2
|
|
|
3
3
|
import { makeSwingStore } from './swingStore.js';
|
|
4
4
|
import { buffer } from './util.js';
|
|
5
|
+
import { validateArtifactMode } from './internal.js';
|
|
5
6
|
import { assertComplete } from './assertComplete.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @typedef { object } ImportSwingStoreOptions
|
|
9
|
-
* @property {
|
|
10
|
+
* @property { import('./internal.js').ArtifactMode } [artifactMode] What artifacts should the importer use and require?
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -16,15 +17,17 @@ import { assertComplete } from './assertComplete.js';
|
|
|
16
17
|
*
|
|
17
18
|
* @param {import('./exporter').SwingStoreExporter} exporter
|
|
18
19
|
* @param {string | null} [dirPath]
|
|
19
|
-
* @param {ImportSwingStoreOptions} options
|
|
20
|
+
* @param {ImportSwingStoreOptions} [options]
|
|
20
21
|
* @returns {Promise<import('./swingStore').SwingStore>}
|
|
21
22
|
*/
|
|
22
23
|
export async function importSwingStore(exporter, dirPath = null, options = {}) {
|
|
23
24
|
if (dirPath && typeof dirPath !== 'string') {
|
|
24
25
|
Fail`dirPath must be a string`;
|
|
25
26
|
}
|
|
26
|
-
const {
|
|
27
|
-
|
|
27
|
+
const { artifactMode = 'operational', ...makeSwingStoreOptions } = options;
|
|
28
|
+
validateArtifactMode(artifactMode);
|
|
29
|
+
|
|
30
|
+
const store = makeSwingStore(dirPath, true, makeSwingStoreOptions);
|
|
28
31
|
const { kernelStorage, internal } = store;
|
|
29
32
|
|
|
30
33
|
// For every exportData entry, we add a DB record. 'kv' entries are
|
|
@@ -81,11 +84,10 @@ export async function importSwingStore(exporter, dirPath = null, options = {}) {
|
|
|
81
84
|
|
|
82
85
|
// All the metadata is now installed, and we're prepared for
|
|
83
86
|
// artifacts. We walk `getArtifactNames()` and offer each one to the
|
|
84
|
-
// submodule, which
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// that check if they want.
|
|
87
|
+
// submodule, which may ignore it according to `artifactMode`, but
|
|
88
|
+
// otherwise validates and accepts it. This is an initial import, so
|
|
89
|
+
// we don't need to check if we already have the data, but the
|
|
90
|
+
// submodule function is free to do such checks.
|
|
89
91
|
|
|
90
92
|
for await (const name of exporter.getArtifactNames()) {
|
|
91
93
|
const makeChunkIterator = () => exporter.getArtifact(name);
|
|
@@ -98,13 +100,13 @@ export async function importSwingStore(exporter, dirPath = null, options = {}) {
|
|
|
98
100
|
await internal.bundleStore.importBundle(name, dataProvider);
|
|
99
101
|
} else if (tag === 'snapshot') {
|
|
100
102
|
await internal.snapStore.populateSnapshot(name, makeChunkIterator, {
|
|
101
|
-
|
|
103
|
+
artifactMode,
|
|
102
104
|
});
|
|
103
105
|
} else if (tag === 'transcript') {
|
|
104
106
|
await internal.transcriptStore.populateTranscriptSpan(
|
|
105
107
|
name,
|
|
106
108
|
makeChunkIterator,
|
|
107
|
-
{
|
|
109
|
+
{ artifactMode },
|
|
108
110
|
);
|
|
109
111
|
} else {
|
|
110
112
|
Fail`unknown artifact type ${q(tag)} on import`;
|
|
@@ -112,9 +114,11 @@ export async function importSwingStore(exporter, dirPath = null, options = {}) {
|
|
|
112
114
|
}
|
|
113
115
|
|
|
114
116
|
// We've installed all the artifacts that we could, now do a
|
|
115
|
-
// completeness check.
|
|
117
|
+
// completeness check. Enforce at least 'operational' completeness,
|
|
118
|
+
// even if the given mode was 'debug'.
|
|
116
119
|
|
|
117
|
-
|
|
120
|
+
const checkMode = artifactMode === 'debug' ? 'operational' : artifactMode;
|
|
121
|
+
assertComplete(internal, checkMode);
|
|
118
122
|
|
|
119
123
|
await exporter.close();
|
|
120
124
|
return store;
|
package/src/internal.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Fail, q } from '@agoric/assert';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @typedef { import('./snapStore').SnapStoreInternal } SnapStoreInternal
|
|
3
5
|
* @typedef { import('./transcriptStore').TranscriptStoreInternal } TranscriptStoreInternal
|
|
@@ -8,7 +10,13 @@
|
|
|
8
10
|
* snapStore: SnapStoreInternal,
|
|
9
11
|
* bundleStore: BundleStoreInternal,
|
|
10
12
|
* }} SwingStoreInternal
|
|
13
|
+
*
|
|
14
|
+
* @typedef {'operational' | 'replay' | 'archival' | 'debug'} ArtifactMode
|
|
11
15
|
*/
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
export {
|
|
17
|
+
export const artifactModes = ['operational', 'replay', 'archival', 'debug'];
|
|
18
|
+
export function validateArtifactMode(artifactMode) {
|
|
19
|
+
if (!artifactModes.includes(artifactMode)) {
|
|
20
|
+
Fail`invalid artifactMode ${q(artifactMode)}`;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/src/repairMetadata.js
CHANGED
|
@@ -60,6 +60,8 @@ export async function doRepairMetadata(internal, exporter) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// and do a completeness check
|
|
63
|
-
|
|
63
|
+
/** @type { import('./internal.js').ArtifactMode } */
|
|
64
|
+
const artifactMode = 'operational';
|
|
65
|
+
assertComplete(internal, artifactMode);
|
|
64
66
|
await exporter.close();
|
|
65
67
|
}
|
package/src/snapStore.js
CHANGED
|
@@ -31,6 +31,7 @@ import { buffer } from './util.js';
|
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
33
|
* @typedef { import('./exporter').SwingStoreExporter } SwingStoreExporter
|
|
34
|
+
* @typedef { import('./internal.js').ArtifactMode } ArtifactMode
|
|
34
35
|
*
|
|
35
36
|
* @typedef {{
|
|
36
37
|
* loadSnapshot: (vatID: string) => AsyncIterableIterator<Uint8Array>,
|
|
@@ -44,10 +45,10 @@ import { buffer } from './util.js';
|
|
|
44
45
|
* @typedef {{
|
|
45
46
|
* exportSnapshot: (name: string) => AsyncIterableIterator<Uint8Array>,
|
|
46
47
|
* getExportRecords: (includeHistorical: boolean) => IterableIterator<readonly [key: string, value: string]>,
|
|
47
|
-
* getArtifactNames: (
|
|
48
|
+
* getArtifactNames: (artifactMode: ArtifactMode) => AsyncIterableIterator<string>,
|
|
48
49
|
* importSnapshotRecord: (key: string, value: string) => void,
|
|
49
|
-
* populateSnapshot: (name: string, makeChunkIterator: () => AnyIterableIterator<Uint8Array>, options: {
|
|
50
|
-
* assertComplete: (
|
|
50
|
+
* populateSnapshot: (name: string, makeChunkIterator: () => AnyIterableIterator<Uint8Array>, options: { artifactMode: ArtifactMode }) => Promise<void>,
|
|
51
|
+
* assertComplete: (checkMode: Omit<ArtifactMode, 'debug'>) => void,
|
|
51
52
|
* repairSnapshotRecord: (key: string, value: string) => void,
|
|
52
53
|
* }} SnapStoreInternal
|
|
53
54
|
*
|
|
@@ -481,11 +482,11 @@ export function makeSnapStore(
|
|
|
481
482
|
}
|
|
482
483
|
}
|
|
483
484
|
|
|
484
|
-
async function* getArtifactNames(
|
|
485
|
+
async function* getArtifactNames(artifactMode) {
|
|
485
486
|
for (const rec of sqlGetAvailableSnapshots.iterate(1)) {
|
|
486
487
|
yield snapshotArtifactName(rec);
|
|
487
488
|
}
|
|
488
|
-
if (
|
|
489
|
+
if (artifactMode === 'debug') {
|
|
489
490
|
for (const rec of sqlGetAvailableSnapshots.iterate(null)) {
|
|
490
491
|
yield snapshotArtifactName(rec);
|
|
491
492
|
}
|
|
@@ -564,12 +565,12 @@ export function makeSnapStore(
|
|
|
564
565
|
* @param {string} name Artifact name of the snapshot
|
|
565
566
|
* @param {() => AnyIterableIterator<Uint8Array>} makeChunkIterator get an iterator of snapshot byte chunks
|
|
566
567
|
* @param {object} options
|
|
567
|
-
* @param {
|
|
568
|
+
* @param {ArtifactMode} options.artifactMode
|
|
568
569
|
* @returns {Promise<void>}
|
|
569
570
|
*/
|
|
570
571
|
async function populateSnapshot(name, makeChunkIterator, options) {
|
|
571
572
|
ensureTxn();
|
|
572
|
-
const {
|
|
573
|
+
const { artifactMode } = options;
|
|
573
574
|
const parts = name.split('.');
|
|
574
575
|
const [type, vatID, rawEndPos] = parts;
|
|
575
576
|
// prettier-ignore
|
|
@@ -580,7 +581,7 @@ export function makeSnapStore(
|
|
|
580
581
|
sqlGetSnapshotHashFor.get(vatID, snapPos) ||
|
|
581
582
|
Fail`no metadata for snapshot ${name}`;
|
|
582
583
|
|
|
583
|
-
if (!metadata.inUse &&
|
|
584
|
+
if (!metadata.inUse && artifactMode !== 'debug') {
|
|
584
585
|
return; // ignore old snapshots
|
|
585
586
|
}
|
|
586
587
|
|
|
@@ -617,8 +618,8 @@ export function makeSnapStore(
|
|
|
617
618
|
`);
|
|
618
619
|
sqlListPrunedCurrentSnapshots.pluck();
|
|
619
620
|
|
|
620
|
-
function assertComplete(
|
|
621
|
-
assert
|
|
621
|
+
function assertComplete(checkMode) {
|
|
622
|
+
assert(checkMode !== 'debug', checkMode);
|
|
622
623
|
// every 'inUse' snapshot must be populated
|
|
623
624
|
const vatIDs = sqlListPrunedCurrentSnapshots.all();
|
|
624
625
|
if (vatIDs.length) {
|