Skip to content

Commit

Permalink
feat: add exporter.getHostKV() API
Browse files Browse the repository at this point in the history
Add a new API to the exporter, `exporter.getHostKV(key)`, so that the
cosmic-swingset state-sync exporter process can query `host.height`
without accidentally creating a read-write transaction too.

refs #8523
  • Loading branch information
warner authored and mhofman committed Dec 6, 2023
1 parent 601e960 commit 43f4e8e
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 0 deletions.
3 changes: 3 additions & 0 deletions packages/cosmic-swingset/src/import-kernel-db.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,9 @@ export const performStateSyncImport = async (
// Represent the data in `exportDir` as a SwingSetExporter object.
/** @type {import('@agoric/swing-store').SwingStoreExporter} */
const exporter = harden({
getHostKV(_key) {
return undefined;
},
async *getExportData() {
log?.('importing export data');
const exportData = createReadStream(
Expand Down
33 changes: 33 additions & 0 deletions packages/swing-store/src/exporter.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ import { validateArtifactMode } from './internal.js';
* the concurrent activity of other swingStore instances, the data representing
* the commit point will stay consistent and available.
*
* @property {(key: string) => string | undefined} getHostKV
*
* Retrieve a value from the "host" portion of the kvStore, just like
* hostStorage.hostKVStore.get() would do.
*
* @property {() => AnyIterableIterator<KVPair>} getExportData
*
* Get a full copy of the first-stage export data (key-value pairs) from the
Expand Down Expand Up @@ -112,6 +117,33 @@ export function makeSwingStoreExporter(dirPath, options = {}) {
assertComplete(internal, artifactMode);
}

const sqlKVGet = db.prepare(`
SELECT value
FROM kvStore
WHERE key = ?
`);
sqlKVGet.pluck(true);

/**
* Obtain the value stored for a given host key. This is for the
* benefit of clients who need to briefly query the DB to ensure
* they are exporting the right thing, and need to avoid modifying
* anything (or creating a read-write DB lock) in the process.
*
* @param {string} key The key whose value is sought.
*
* @returns {string | undefined} the (string) value for the given key, or
* undefined if there is no such value.
*
* @throws if key is not a string, or the key is not in the host
* section
*/
function getHostKV(key) {
typeof key === 'string' || Fail`key must be a string`;
getKeyType(key) === 'host' || Fail`getHostKV requires host keys`;
return sqlKVGet.get(key);
}

const sqlGetAllKVData = db.prepare(`
SELECT key, value
FROM kvStore
Expand Down Expand Up @@ -173,6 +205,7 @@ export function makeSwingStoreExporter(dirPath, options = {}) {
}

return harden({
getHostKV,
getExportData,
getArtifactNames,
getArtifact,
Expand Down
6 changes: 6 additions & 0 deletions packages/swing-store/test/test-bundles.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ test('b0 import', async t => {
const idA = makeB0ID(b0A);
const nameA = `bundle.${idA}`;
const exporter = {
getHostKV(_key) {
return undefined;
},
async *getExportData() {
yield /** @type {const} */ ([nameA, idA]);
},
Expand Down Expand Up @@ -135,6 +138,9 @@ test('b0 bad import', async t => {
const idA = makeB0ID(b0A);
const nameA = `bundle.${idA}`;
const exporter = {
getHostKV(_key) {
return undefined;
},
async *getExportData() {
yield /** @type {const} */ ([nameA, idA]);
},
Expand Down
9 changes: 9 additions & 0 deletions packages/swing-store/test/test-export.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ const exportTest = test.macro(async (t, mode) => {
const ss1 = initSwingStore(dbDir, options);
const ks = ss1.kernelStorage;

ss1.hostStorage.kvStore.set('host.h1', 'hostvalue1');

// build a DB with four spans (one in an old incarnation, two
// historical but current incarnation, only one inUse) and two
// snapshots (only one inUSe)
Expand Down Expand Up @@ -88,6 +90,13 @@ const exportTest = test.macro(async (t, mode) => {
}
const exporter = makeSwingStoreExporter(dbDir, { artifactMode });

// hostKV
t.is(exporter.getHostKV('host.h1'), 'hostvalue1');
t.is(exporter.getHostKV('host.hmissing'), undefined);
t.throws(() => exporter.getHostKV('nonhost'), {
message: 'getHostKV requires host keys',
});

// exportData
{
const exportData = new Map();
Expand Down
3 changes: 3 additions & 0 deletions packages/swing-store/test/test-import.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ function convert(orig) {
*/
export function makeExporter(exportData, artifacts) {
return {
getHostKV(_key) {
return undefined;
},
async *getExportData() {
for (const [key, value] of exportData.entries()) {
/** @type { KVPair } */
Expand Down

0 comments on commit 43f4e8e

Please sign in to comment.