@dstanesc/o-o-o-o-o-o-o
Version:
O-O-O-O-O-O-O is a collection of content addressed persistent data structures
259 lines (240 loc) • 7.12 kB
text/typescript
import { compute_chunks } from '@dstanesc/wasm-chunking-fastcdc-node'
import { chunkerFactory } from '../chunking'
import { GraphStore, graphStoreFactory } from '../graph-store'
import { Graph } from '../graph'
import {
BlockStore,
MemoryBlockStore,
memoryBlockStoreFactory,
} from '../block-store'
import {
LinkCodec,
linkCodecFactory,
ValueCodec,
valueCodecFactory,
} from '../codecs'
import * as assert from 'assert'
import { navigateVertices, PathElemType, RequestBuilder } from '../navigate'
import {
Link,
Offset,
Part,
Prop,
Comment,
Tag,
Block,
Version,
} from '../types'
import { VersionStore, versionStoreFactory } from '../version-store'
import { graphPackerFactory } from '../graph-packer'
/**
* Some proto-schema
*/
enum ObjectTypes {
FOLDER = 1,
FILE = 2,
}
enum RlshpTypes {
CONTAINS = 1,
}
enum PropTypes {
META = 1,
DATA = 2,
}
enum KeyTypes {
NAME = 1,
CONTENT = 2,
}
const { chunk } = chunkerFactory(512, compute_chunks)
const linkCodec: LinkCodec = linkCodecFactory()
const valueCodec: ValueCodec = valueCodecFactory()
const {
packVersionStore,
restoreSingleIndex: restoreVersionStore,
packGraphVersion,
restoreGraphVersion,
} = graphPackerFactory(linkCodec)
const blockStore1: MemoryBlockStore = memoryBlockStoreFactory()
describe('Version pack and restore', function () {
test('edit, bundle, restore, edit, bundle, restore, query', async () => {
const versionStore: VersionStore = await versionStoreFactory({
chunk,
linkCodec,
valueCodec,
blockStore: blockStore1,
})
const graphStore: GraphStore = graphStoreFactory({
chunk,
linkCodec,
valueCodec,
blockStore: blockStore1,
})
const g = new Graph(versionStore, graphStore)
const tx = g.tx()
await tx.start()
const v1 = tx.addVertex(ObjectTypes.FOLDER)
const v2 = tx.addVertex(ObjectTypes.FOLDER)
const v3 = tx.addVertex(ObjectTypes.FILE)
const e1 = await tx.addEdge(v1, v2, RlshpTypes.CONTAINS)
const e2 = await tx.addEdge(v1, v3, RlshpTypes.CONTAINS)
await tx.addVertexProp(v1, KeyTypes.NAME, 'root-folder', PropTypes.META)
await tx.addVertexProp(
v2,
KeyTypes.NAME,
'nested-folder',
PropTypes.META
)
await tx.addVertexProp(v3, KeyTypes.NAME, 'nested-file', PropTypes.META)
await tx.addVertexProp(
v2,
KeyTypes.CONTENT,
'hello world from v2',
PropTypes.DATA
)
await tx.addVertexProp(
v3,
KeyTypes.CONTENT,
'hello world from v3',
PropTypes.DATA
)
const { root: original } = await tx.commit({})
/**
* Pack version store
*/
const versionStoreBundle: Block = await packVersionStore(
versionStore.versionStoreRoot(),
blockStore1,
chunk,
valueCodec
)
/**
* Pack last version
*/
const graphStoreBundle: Block = await packGraphVersion(
original,
blockStore1
)
/**
* Empty block store
*/
const memoryStore: BlockStore = memoryBlockStoreFactory()
/**
* Restore version store into the empty block store
*/
const { root: storeRoot } = await restoreVersionStore(
versionStoreBundle.bytes,
memoryStore
)
/**
* Restore last version into the empty block store
*/
const { root: versionRoot } = await restoreGraphVersion(
graphStoreBundle.bytes,
memoryStore
)
/**
* Edit restored version
*/
const versionStore1: VersionStore = await versionStoreFactory({
storeRoot,
versionRoot,
chunk,
linkCodec,
valueCodec,
blockStore: memoryStore,
})
const graphStore1 = graphStoreFactory({
chunk,
linkCodec,
valueCodec,
blockStore: memoryStore,
})
const g1 = new Graph(versionStore1, graphStore1)
const tx1 = g1.tx()
await tx1.start()
const v10 = await tx1.getVertex(0)
const v11 = tx1.addVertex(ObjectTypes.FILE)
const e11 = await tx1.addEdge(v10, v11, RlshpTypes.CONTAINS)
await tx1.addVertexProp(
v11,
KeyTypes.NAME,
'nested-file-user-1',
PropTypes.META
)
await tx1.addVertexProp(
v11,
KeyTypes.CONTENT,
'hello world from v11',
PropTypes.DATA
)
const { root: first } = await tx1.commit({})
/**
* Pack newest version store
*/
const versionStoreBundle1: Block = await packVersionStore(
versionStore1.versionStoreRoot(),
memoryStore,
chunk,
valueCodec
)
/**
* Pack newest version
*/
const graphStoreBundle1: Block = await packGraphVersion(
first,
memoryStore
)
/**
* Empty block store
*/
const memoryStore1: BlockStore = memoryBlockStoreFactory()
/**
* Restore newest version store into the empty block store
*/
const { root: storeRoot1 } = await restoreVersionStore(
versionStoreBundle1.bytes,
memoryStore1
)
/**
* Restore newest graph version into the empty block store
*/
const { root: versionRoot1 } = await restoreGraphVersion(
graphStoreBundle1.bytes,
memoryStore1
)
const versionStore2: VersionStore = await versionStoreFactory({
storeRoot: storeRoot1,
versionRoot: versionRoot1,
chunk,
linkCodec,
valueCodec,
blockStore: memoryStore1,
})
const graphStore2 = graphStoreFactory({
chunk,
linkCodec,
valueCodec,
blockStore: memoryStore1,
})
const g2 = new Graph(versionStore2, graphStore2)
const vr = await query(g2)
assert.strictEqual(vr.length, 3)
assert.strictEqual(vr[0].value, 'nested-folder')
assert.strictEqual(vr[1].value, 'nested-file')
assert.strictEqual(vr[2].value, 'nested-file-user-1')
})
})
const query = async (graph: Graph): Promise<Prop[]> => {
const request = new RequestBuilder()
.add(PathElemType.VERTEX)
.add(PathElemType.EDGE)
.add(PathElemType.VERTEX)
.extract(KeyTypes.NAME)
.maxResults(100)
.get()
const vr: Prop[] = []
for await (const result of navigateVertices(graph, [0], request)) {
vr.push(result as Prop)
}
return vr
}