Skip to content

Commit

Permalink
feat: decode with coreDiscoveryId or coreDiscoveryKey
Browse files Browse the repository at this point in the history
Allow decode to work when a coreDiscoveryId is
passed, instead of coreDiscoveryKey to match an
upstream change in the multi-core-indexer to use
coreDiscoveryId rather than coreDiscoveryKey. This
reduces a round-trip conversion from buffer to
string, and will also facilitate sending entries
between threads when we run indexing in a separate
worker thread.
  • Loading branch information
gmaclennan committed Sep 24, 2024
1 parent 1790825 commit 65113ab
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 22 deletions.
9 changes: 3 additions & 6 deletions src/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import cenc from 'compact-encoding'
import { DATA_TYPE_ID_BYTES, SCHEMA_VERSION_BYTES } from './constants.js'
import {
ExhaustivenessError,
VersionIdObject,
VersionObject,
getOwn,
getProtoTypeName,
} from './lib/utils.js'
Expand All @@ -42,12 +42,9 @@ for (const [schemaName, dataTypeId] of Object.entries(dataTypeIds) as Array<
* Decode a Buffer as an object validated against the corresponding schema
*
* @param buf Buffer to be decoded
* @param versionObj public key (coreKey) of the core where this block is stored, and the index of the block in the core.
* @param versionObj discovery key or discovery id of the core where this block is stored, and the index of the block in the core.
* */
export function decode(
buf: Buffer,
versionObj: VersionIdObject
): MapeoDocDecode {
export function decode(buf: Buffer, versionObj: VersionObject): MapeoDocDecode {
const schemaDef = decodeBlockPrefix(buf)

const encodedMsg = buf.subarray(
Expand Down
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ export {
getVersionId,
parseVersionId,
valueOf,
type VersionIdObject,
/** Deprecated: rename VersionIdObject to VersionObject */
type VersionObject as VersionIdObject,
type VersionObject,
} from './lib/utils.js'

export * from './schema/index.js'
Expand Down
6 changes: 3 additions & 3 deletions src/lib/decode-conversions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ import {
assert,
ExhaustivenessError,
getVersionId,
VersionIdObject,
VersionObject,
} from './utils.js'

/** Function type for converting a protobuf type of any version for a particular
* schema name, and returning the most recent JSONSchema type */
type ConvertFunction<TSchemaName extends SchemaName> = (
message: Extract<ProtoTypesWithSchemaInfo, { schemaName: TSchemaName }>,
versionObj: VersionIdObject
versionObj: VersionObject
) => FilterBySchemaName<MapeoDocDecode, TSchemaName>

function ensure(
Expand Down Expand Up @@ -465,7 +465,7 @@ function convertTagPrimitive({

function convertCommon(
common: ProtoTypesWithSchemaInfo['common'],
versionObj: VersionIdObject
versionObj: VersionObject
): Omit<MapeoCommon, 'schemaName'> {
if (
!common ||
Expand Down
44 changes: 32 additions & 12 deletions src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,28 +37,48 @@ function capitalize<T extends string>(str: T): Capitalize<T> {
return (str.charAt(0).toUpperCase() + str.slice(1)) as any
}

export type VersionIdObject = {
export type VersionObject = VersionDiscoveryKeyObject | VersionDiscoveryIdObject

export type VersionDiscoveryKeyObject = {
coreDiscoveryKey: Buffer
index: number
}

export type VersionDiscoveryIdObject = {
coreDiscoveryId: string
index: number
}

export const VERSION_ID_SEPARATOR = '/'

/**
* Get a string versionId from a core key and index in that core. A versionId
* uniquely identifies a record in the underlying Hypercore storage used by
* Mapeo
* Get a string versionId from a core discovery key or discovery id and index in
* that core. A versionId uniquely identifies a record in the underlying
* Hypercore storage used by Mapeo
* @param versionIdObject
* @returns versionId string
*/
export function getVersionId({ coreDiscoveryKey, index }: VersionIdObject) {
assert(
coreDiscoveryKey.byteLength >= 32,
'version ID core discovery key must be have at least 32 bytes'
)
export function getVersionId(versionIdObject: VersionObject) {
const { index } = versionIdObject
assert(
Number.isSafeInteger(index) && index >= 0,
'version ID index must be a non-negative integer'
)
return coreDiscoveryKey.toString('hex') + '/' + index
let discoveryId
if ('coreDiscoveryId' in versionIdObject) {
discoveryId = versionIdObject.coreDiscoveryId
assert(
discoveryId.length > 0,
'version ID core discovery id must be non-empty string'
)
} else {
assert(
versionIdObject.coreDiscoveryKey.byteLength >= 32,
'version ID core discovery key must be have at least 32 bytes'
)
discoveryId = versionIdObject.coreDiscoveryKey.toString('hex')
}
return discoveryId + VERSION_ID_SEPARATOR + index
}

/**
Expand All @@ -68,8 +88,8 @@ export function getVersionId({ coreDiscoveryKey, index }: VersionIdObject) {
* @param versionId hex-encoded 32-byte core key and index in the core, separated with `/`
* @returns coreKey as a Buffer and index in the core
*/
export function parseVersionId(versionId: string): VersionIdObject {
const items = versionId.split('/')
export function parseVersionId(versionId: string): VersionDiscoveryKeyObject {
const items = versionId.split(VERSION_ID_SEPARATOR)
if (!items[0] || !items[1]) throw new Error('Invalid versionId')
const coreDiscoveryKey = Buffer.from(items[0], 'hex')
if (coreDiscoveryKey.length !== 32) throw new Error('Invalid versionId')
Expand Down

0 comments on commit 65113ab

Please sign in to comment.