@dxos/feed-store 0.6.12 → 0.6.13-main.548ca8d
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/dist/lib/browser/{chunk-QEVMM5RF.mjs → chunk-QYBKGLQJ.mjs} +2 -3
- package/dist/lib/browser/chunk-QYBKGLQJ.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +1 -1
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/testing/index.mjs +1 -1
- package/dist/lib/node/{chunk-CEOKPJ6P.cjs → chunk-PXGR6322.cjs} +5 -6
- package/dist/lib/node/chunk-PXGR6322.cjs.map +7 -0
- package/dist/lib/node/index.cjs +4 -4
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/testing/index.cjs +3 -3
- package/dist/lib/node-esm/chunk-QELQFW6D.mjs +495 -0
- package/dist/lib/node-esm/chunk-QELQFW6D.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +567 -0
- package/dist/lib/node-esm/index.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -0
- package/dist/lib/node-esm/testing/index.mjs +154 -0
- package/dist/lib/node-esm/testing/index.mjs.map +7 -0
- package/dist/types/src/feed-queue.browser.test.d.ts +2 -0
- package/dist/types/src/feed-queue.browser.test.d.ts.map +1 -0
- package/dist/types/src/feed-store.node.test.d.ts +2 -0
- package/dist/types/src/feed-store.node.test.d.ts.map +1 -0
- package/package.json +21 -19
- package/src/feed-factory.test.ts +1 -1
- package/src/feed-iterator.test.ts +2 -3
- package/src/feed-queue.browser.test.ts +54 -0
- package/src/feed-queue.test.ts +50 -92
- package/src/feed-set-iterator.test.ts +3 -4
- package/src/feed-store.node.test.ts +56 -0
- package/src/feed-store.test.ts +2 -51
- package/src/feed-wrapper.test.ts +3 -7
- package/src/feed-wrapper.ts +1 -1
- package/dist/lib/browser/chunk-QEVMM5RF.mjs.map +0 -7
- package/dist/lib/node/chunk-CEOKPJ6P.cjs.map +0 -7
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
FeedFactory,
|
|
4
|
+
FeedStore
|
|
5
|
+
} from "../chunk-QELQFW6D.mjs";
|
|
6
|
+
|
|
7
|
+
// packages/common/feed-store/src/testing/mocks.ts
|
|
8
|
+
import { Event, scheduleTask } from "@dxos/async";
|
|
9
|
+
import { Context } from "@dxos/context";
|
|
10
|
+
import { PublicKey } from "@dxos/keys";
|
|
11
|
+
var __dxlog_file = "/home/runner/work/dxos/dxos/packages/common/feed-store/src/testing/mocks.ts";
|
|
12
|
+
var MockFeedWriter = class {
|
|
13
|
+
constructor(feedKey = PublicKey.random()) {
|
|
14
|
+
this.feedKey = feedKey;
|
|
15
|
+
this.written = new Event();
|
|
16
|
+
this.messages = [];
|
|
17
|
+
}
|
|
18
|
+
async write(data, { afterWrite } = {}) {
|
|
19
|
+
this.messages.push(data);
|
|
20
|
+
const receipt = {
|
|
21
|
+
feedKey: this.feedKey,
|
|
22
|
+
seq: this.messages.length - 1
|
|
23
|
+
};
|
|
24
|
+
await afterWrite?.(receipt);
|
|
25
|
+
scheduleTask(new Context(void 0, {
|
|
26
|
+
F: __dxlog_file,
|
|
27
|
+
L: 30
|
|
28
|
+
}), () => {
|
|
29
|
+
this.written.emit([
|
|
30
|
+
data,
|
|
31
|
+
receipt
|
|
32
|
+
]);
|
|
33
|
+
});
|
|
34
|
+
return receipt;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// packages/common/feed-store/src/testing/test-builder.ts
|
|
39
|
+
import { Keyring } from "@dxos/keyring";
|
|
40
|
+
import { createStorage, StorageType } from "@dxos/random-access-storage";
|
|
41
|
+
|
|
42
|
+
// packages/common/feed-store/src/testing/test-generator.ts
|
|
43
|
+
import { sleep } from "@dxos/async";
|
|
44
|
+
import { createCodecEncoding } from "@dxos/hypercore";
|
|
45
|
+
import { faker } from "@dxos/random";
|
|
46
|
+
var defaultCodec = {
|
|
47
|
+
encode: (obj) => Buffer.from(JSON.stringify(obj)),
|
|
48
|
+
decode: (buffer) => JSON.parse(buffer.toString())
|
|
49
|
+
};
|
|
50
|
+
var defaultValueEncoding = createCodecEncoding(defaultCodec);
|
|
51
|
+
var defaultTestBlockGenerator = (i) => ({
|
|
52
|
+
id: faker.string.uuid(),
|
|
53
|
+
index: i,
|
|
54
|
+
value: faker.lorem.sentence()
|
|
55
|
+
});
|
|
56
|
+
var TestGenerator = class {
|
|
57
|
+
constructor(_generate) {
|
|
58
|
+
this._generate = _generate;
|
|
59
|
+
this._count = 0;
|
|
60
|
+
}
|
|
61
|
+
async writeBlocks(writer, { count = 1, delay } = {}) {
|
|
62
|
+
return await Promise.all(Array.from(Array(count)).map(async () => {
|
|
63
|
+
const data = this._generate(this._count++);
|
|
64
|
+
const receipt = await writer.write(data);
|
|
65
|
+
if (delay) {
|
|
66
|
+
await sleep(faker.number.int(delay));
|
|
67
|
+
}
|
|
68
|
+
return receipt;
|
|
69
|
+
}));
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
var defaultTestGenerator = new TestGenerator(defaultTestBlockGenerator);
|
|
73
|
+
|
|
74
|
+
// packages/common/feed-store/src/testing/test-builder.ts
|
|
75
|
+
var evaluate = (builder, arg) => arg === "function" ? arg(builder) : arg;
|
|
76
|
+
var TestBuilder = class _TestBuilder {
|
|
77
|
+
static {
|
|
78
|
+
this.ROOT_DIR = "feeds";
|
|
79
|
+
}
|
|
80
|
+
constructor(_properties = {}) {
|
|
81
|
+
this._properties = _properties;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Creates a new builder with the current builder's properties.
|
|
85
|
+
*/
|
|
86
|
+
clone() {
|
|
87
|
+
return new _TestBuilder(Object.assign({}, this._properties));
|
|
88
|
+
}
|
|
89
|
+
get keyring() {
|
|
90
|
+
return this._properties.keyring ??= new Keyring();
|
|
91
|
+
}
|
|
92
|
+
get storage() {
|
|
93
|
+
return this._properties.storage ??= createStorage({
|
|
94
|
+
type: StorageType.RAM
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
get root() {
|
|
98
|
+
return this._properties.root ??= this.storage.createDirectory(_TestBuilder.ROOT_DIR);
|
|
99
|
+
}
|
|
100
|
+
setKeyring(keyring) {
|
|
101
|
+
this._properties.keyring = evaluate(this, keyring);
|
|
102
|
+
return this;
|
|
103
|
+
}
|
|
104
|
+
setStorage(storage, root) {
|
|
105
|
+
this._properties.storage = evaluate(this, storage);
|
|
106
|
+
if (root) {
|
|
107
|
+
this._properties.root = this.storage.createDirectory(root);
|
|
108
|
+
}
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
setRoot(root) {
|
|
112
|
+
this._properties.root = evaluate(this, root);
|
|
113
|
+
return this;
|
|
114
|
+
}
|
|
115
|
+
createFeedFactory() {
|
|
116
|
+
return new FeedFactory({
|
|
117
|
+
root: this.root,
|
|
118
|
+
signer: this.keyring,
|
|
119
|
+
hypercore: {
|
|
120
|
+
valueEncoding: this._properties.valueEncoding
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
createFeedStore() {
|
|
125
|
+
return new FeedStore({
|
|
126
|
+
factory: this.createFeedFactory()
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
var TestItemBuilder = class extends TestBuilder {
|
|
131
|
+
constructor() {
|
|
132
|
+
super({
|
|
133
|
+
valueEncoding: defaultValueEncoding,
|
|
134
|
+
generator: defaultTestGenerator
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
get valueEncoding() {
|
|
138
|
+
return this._properties.valueEncoding;
|
|
139
|
+
}
|
|
140
|
+
get generator() {
|
|
141
|
+
return this._properties.generator;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
export {
|
|
145
|
+
MockFeedWriter,
|
|
146
|
+
TestBuilder,
|
|
147
|
+
TestGenerator,
|
|
148
|
+
TestItemBuilder,
|
|
149
|
+
defaultCodec,
|
|
150
|
+
defaultTestBlockGenerator,
|
|
151
|
+
defaultTestGenerator,
|
|
152
|
+
defaultValueEncoding
|
|
153
|
+
};
|
|
154
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/testing/mocks.ts", "../../../../src/testing/test-builder.ts", "../../../../src/testing/test-generator.ts"],
|
|
4
|
+
"sourcesContent": ["//\n// Copyright 2022 DXOS.org\n//\n\nimport { Event, scheduleTask } from '@dxos/async';\nimport { Context } from '@dxos/context';\nimport { PublicKey } from '@dxos/keys';\n\nimport type { FeedWriter, WriteOptions, WriteReceipt } from '../feed-writer';\n\n/**\n * Mock writer collects and emits messages.\n */\nexport class MockFeedWriter<T extends {}> implements FeedWriter<T> {\n public readonly written = new Event<[T, WriteReceipt]>();\n public readonly messages: T[] = [];\n\n constructor(readonly feedKey = PublicKey.random()) {}\n\n async write(data: T, { afterWrite }: WriteOptions = {}): Promise<WriteReceipt> {\n this.messages.push(data);\n\n const receipt: WriteReceipt = {\n feedKey: this.feedKey,\n seq: this.messages.length - 1,\n };\n\n await afterWrite?.(receipt);\n\n scheduleTask(new Context(), () => {\n this.written.emit([data, receipt]);\n });\n\n return receipt;\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport type { ValueEncoding } from 'hypercore';\n\nimport { Keyring } from '@dxos/keyring';\nimport { createStorage, type Directory, type Storage, StorageType } from '@dxos/random-access-storage';\n\nimport { defaultTestGenerator, defaultValueEncoding, type TestGenerator, type TestItem } from './test-generator';\nimport { FeedFactory } from '../feed-factory';\nimport { FeedStore } from '../feed-store';\n\nexport type TestBuilderOptions<T extends {}> = {\n storage?: Storage;\n root?: Directory;\n keyring?: Keyring;\n valueEncoding?: ValueEncoding<T>;\n generator?: TestGenerator<T>;\n};\n\ntype PropertyProvider<T extends {}, P> = (cb: TestBuilder<T>) => P;\n\nconst evaluate = <T extends {}, P>(builder: TestBuilder<T>, arg: P | PropertyProvider<T, P>) =>\n arg === 'function' ? (arg as Function)(builder) : arg;\n\n/**\n * The builder provides building blocks for tests with sensible defaults.\n * - Factory methods trigger the automatic generation of unset required properties.\n * - Avoids explosion of overly specific test functions that require and return large bags of properties.\n */\nexport class TestBuilder<T extends {}> {\n static readonly ROOT_DIR = 'feeds';\n\n constructor(public readonly _properties: TestBuilderOptions<T> = {}) {}\n\n /**\n * Creates a new builder with the current builder's properties.\n */\n clone(): TestBuilder<T> {\n return new TestBuilder<T>(Object.assign({}, this._properties));\n }\n\n get keyring(): Keyring {\n return (this._properties.keyring ??= new Keyring());\n }\n\n get storage(): Storage {\n return (this._properties.storage ??= createStorage({ type: StorageType.RAM }));\n }\n\n get root(): Directory {\n return (this._properties.root ??= this.storage.createDirectory(TestBuilder.ROOT_DIR));\n }\n\n setKeyring(keyring: Keyring | PropertyProvider<T, Keyring>) {\n this._properties.keyring = evaluate(this, keyring);\n return this;\n }\n\n setStorage(storage: Storage, root?: string) {\n this._properties.storage = evaluate(this, storage);\n if (root) {\n this._properties.root = this.storage.createDirectory(root);\n }\n\n return this;\n }\n\n setRoot(root: Directory) {\n this._properties.root = evaluate(this, root);\n return this;\n }\n\n createFeedFactory() {\n return new FeedFactory<T>({\n root: this.root,\n signer: this.keyring,\n hypercore: {\n valueEncoding: this._properties.valueEncoding,\n },\n });\n }\n\n createFeedStore() {\n return new FeedStore<T>({\n factory: this.createFeedFactory(),\n });\n }\n}\n\n/**\n * Builder with default encoder and generator.\n */\nexport class TestItemBuilder extends TestBuilder<TestItem> {\n constructor() {\n super({\n valueEncoding: defaultValueEncoding,\n generator: defaultTestGenerator,\n });\n }\n\n get valueEncoding() {\n return this._properties.valueEncoding!;\n }\n\n get generator() {\n return this._properties.generator!;\n }\n}\n", "//\n// Copyright 2022 DXOS.org\n//\n\nimport type { AbstractValueEncoding } from 'hypercore';\n\nimport { sleep } from '@dxos/async';\nimport { type Codec } from '@dxos/codec-protobuf';\nimport { createCodecEncoding } from '@dxos/hypercore';\nimport { faker } from '@dxos/random';\n\nimport { type FeedWriter } from '../feed-writer';\n\nexport type TestItem = {\n id: string;\n index: number;\n value: string;\n};\n\nexport const defaultCodec: Codec<any> = {\n encode: (obj: any) => Buffer.from(JSON.stringify(obj)),\n decode: (buffer: Uint8Array) => JSON.parse(buffer.toString()),\n};\n\nexport const defaultValueEncoding: AbstractValueEncoding<any> = createCodecEncoding(defaultCodec);\n\nexport type TestBlockGenerator<T> = (i: number) => T;\n\nexport const defaultTestBlockGenerator: TestBlockGenerator<TestItem> = (i) => ({\n id: faker.string.uuid(),\n index: i,\n value: faker.lorem.sentence(),\n});\n\n/**\n * Writes data to feeds.\n */\nexport class TestGenerator<T extends {}> {\n _count = 0;\n\n constructor(private readonly _generate: TestBlockGenerator<T>) {}\n\n async writeBlocks(\n writer: FeedWriter<T>,\n {\n count = 1,\n delay,\n }: {\n count?: number;\n delay?: {\n min: number;\n max: number;\n };\n } = {},\n ) {\n return await Promise.all(\n Array.from(Array(count)).map(async () => {\n const data = this._generate(this._count++);\n const receipt = await writer.write(data);\n if (delay) {\n await sleep(faker.number.int(delay));\n }\n\n return receipt;\n }),\n );\n }\n}\n\nexport const defaultTestGenerator = new TestGenerator<TestItem>(defaultTestBlockGenerator);\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["Event", "scheduleTask", "Context", "PublicKey", "MockFeedWriter", "constructor", "feedKey", "random", "written", "messages", "write", "data", "afterWrite", "push", "receipt", "seq", "length", "emit", "Keyring", "createStorage", "StorageType", "sleep", "createCodecEncoding", "faker", "defaultCodec", "encode", "obj", "Buffer", "from", "JSON", "stringify", "decode", "buffer", "parse", "toString", "defaultValueEncoding", "createCodecEncoding", "defaultTestBlockGenerator", "i", "id", "faker", "string", "uuid", "index", "value", "lorem", "sentence", "TestGenerator", "constructor", "_generate", "_count", "writeBlocks", "writer", "count", "delay", "Promise", "all", "Array", "map", "data", "receipt", "write", "sleep", "number", "int", "defaultTestGenerator", "evaluate", "builder", "arg", "TestBuilder", "ROOT_DIR", "constructor", "_properties", "clone", "Object", "assign", "keyring", "Keyring", "storage", "createStorage", "type", "StorageType", "RAM", "root", "createDirectory", "setKeyring", "setStorage", "setRoot", "createFeedFactory", "FeedFactory", "signer", "hypercore", "valueEncoding", "createFeedStore", "FeedStore", "factory", "TestItemBuilder", "defaultValueEncoding", "generator", "defaultTestGenerator"]
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-queue.browser.test.d.ts","sourceRoot":"","sources":["../../../src/feed-queue.browser.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feed-store.node.test.d.ts","sourceRoot":"","sources":["../../../src/feed-store.node.test.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/feed-store",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.13-main.548ca8d",
|
|
4
4
|
"description": "A consistent store for hypercore feeds.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -10,14 +10,16 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"browser": "./dist/lib/browser/index.mjs",
|
|
12
12
|
"node": {
|
|
13
|
-
"
|
|
13
|
+
"require": "./dist/lib/node/index.cjs",
|
|
14
|
+
"default": "./dist/lib/node-esm/index.mjs"
|
|
14
15
|
},
|
|
15
16
|
"types": "./dist/types/src/index.d.ts"
|
|
16
17
|
},
|
|
17
18
|
"./testing": {
|
|
18
19
|
"browser": "./dist/lib/browser/testing/index.mjs",
|
|
19
20
|
"node": {
|
|
20
|
-
"
|
|
21
|
+
"require": "./dist/lib/node/testing/index.cjs",
|
|
22
|
+
"default": "./dist/lib/node-esm/testing/index.mjs"
|
|
21
23
|
},
|
|
22
24
|
"types": "./dist/types/src/testing/index.d.ts"
|
|
23
25
|
}
|
|
@@ -40,27 +42,27 @@
|
|
|
40
42
|
"lodash.defaultsdeep": "^4.6.1",
|
|
41
43
|
"race-as-promised": "^0.0.2",
|
|
42
44
|
"streamx": "^2.12.5",
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/context": "0.6.
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/log": "0.6.
|
|
53
|
-
"@dxos/util": "0.6.
|
|
54
|
-
"@dxos/random-access-storage": "0.6.
|
|
55
|
-
"@dxos/node-std": "0.6.
|
|
45
|
+
"@dxos/codec-protobuf": "0.6.13-main.548ca8d",
|
|
46
|
+
"@dxos/async": "0.6.13-main.548ca8d",
|
|
47
|
+
"@dxos/context": "0.6.13-main.548ca8d",
|
|
48
|
+
"@dxos/crypto": "0.6.13-main.548ca8d",
|
|
49
|
+
"@dxos/invariant": "0.6.13-main.548ca8d",
|
|
50
|
+
"@dxos/hypercore": "0.6.13-main.548ca8d",
|
|
51
|
+
"@dxos/debug": "0.6.13-main.548ca8d",
|
|
52
|
+
"@dxos/keys": "0.6.13-main.548ca8d",
|
|
53
|
+
"@dxos/keyring": "0.6.13-main.548ca8d",
|
|
54
|
+
"@dxos/log": "0.6.13-main.548ca8d",
|
|
55
|
+
"@dxos/util": "0.6.13-main.548ca8d",
|
|
56
|
+
"@dxos/random-access-storage": "0.6.13-main.548ca8d",
|
|
57
|
+
"@dxos/node-std": "0.6.13-main.548ca8d"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|
|
58
60
|
"@types/lodash.defaultsdeep": "^4.6.6",
|
|
59
|
-
"@dxos/keys": "0.6.
|
|
60
|
-
"@dxos/random": "0.6.
|
|
61
|
+
"@dxos/keys": "0.6.13-main.548ca8d",
|
|
62
|
+
"@dxos/random": "0.6.13-main.548ca8d"
|
|
61
63
|
},
|
|
62
64
|
"optionalDependencies": {
|
|
63
|
-
"@dxos/random": "0.6.
|
|
65
|
+
"@dxos/random": "0.6.13-main.548ca8d"
|
|
64
66
|
},
|
|
65
67
|
"publishConfig": {
|
|
66
68
|
"access": "public"
|
package/src/feed-factory.test.ts
CHANGED
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from '
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { latch } from '@dxos/async';
|
|
8
|
-
import { describe, test } from '@dxos/test';
|
|
9
8
|
|
|
10
9
|
import { FeedIterator } from './feed-iterator';
|
|
11
10
|
import { TestItemBuilder } from './testing';
|
|
@@ -54,5 +53,5 @@ describe('FeedIterator', () => {
|
|
|
54
53
|
}
|
|
55
54
|
|
|
56
55
|
expect(iterator.isRunning).to.be.false;
|
|
57
|
-
})
|
|
56
|
+
});
|
|
58
57
|
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { sleep, untilError, untilPromise } from '@dxos/async';
|
|
8
|
+
import { log } from '@dxos/log';
|
|
9
|
+
import { StorageType, createStorage } from '@dxos/random-access-storage';
|
|
10
|
+
|
|
11
|
+
import { FeedQueue } from './feed-queue';
|
|
12
|
+
import { TestItemBuilder } from './testing';
|
|
13
|
+
|
|
14
|
+
describe('FeedQueue', () => {
|
|
15
|
+
const builder = new TestItemBuilder();
|
|
16
|
+
|
|
17
|
+
test('works with webfs', async () => {
|
|
18
|
+
const localBuilder = builder.clone().setStorage(createStorage({ type: StorageType.WEBFS }));
|
|
19
|
+
const feedStore = localBuilder.createFeedStore();
|
|
20
|
+
const key = await localBuilder.keyring.createKey();
|
|
21
|
+
const feed = await feedStore.openFeed(key, { writable: true });
|
|
22
|
+
|
|
23
|
+
const queue = new FeedQueue<any>(feed);
|
|
24
|
+
await queue.open();
|
|
25
|
+
|
|
26
|
+
expect(queue.isOpen).to.be.true;
|
|
27
|
+
expect(queue.feed.properties.closed).to.be.false;
|
|
28
|
+
|
|
29
|
+
// Write blocks.
|
|
30
|
+
// TODO(burdon): Write slowly to test writing close feed.
|
|
31
|
+
await localBuilder._properties.generator!.writeBlocks(feed.createFeedWriter(), { count: 10 });
|
|
32
|
+
|
|
33
|
+
// Read until queue closed (pop throws exception).
|
|
34
|
+
const errorPromise = untilError(async () => {
|
|
35
|
+
while (true) {
|
|
36
|
+
const next = await queue.pop();
|
|
37
|
+
log('next', { next: next.seq });
|
|
38
|
+
await sleep(50);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
// Close the queue.
|
|
43
|
+
await untilPromise(async () => {
|
|
44
|
+
await sleep(400);
|
|
45
|
+
await queue.close();
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Expect pop to throw error when queue is closed.
|
|
49
|
+
await errorPromise;
|
|
50
|
+
|
|
51
|
+
expect(queue.isOpen).to.be.false;
|
|
52
|
+
expect(queue.feed.properties.closed).to.be.false;
|
|
53
|
+
});
|
|
54
|
+
});
|
package/src/feed-queue.test.ts
CHANGED
|
@@ -2,12 +2,10 @@
|
|
|
2
2
|
// Copyright 2022 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from '
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { latch, asyncTimeout, sleep, untilError, untilPromise } from '@dxos/async';
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
|
-
import { StorageType, createStorage } from '@dxos/random-access-storage';
|
|
10
|
-
import { describe, test } from '@dxos/test';
|
|
11
9
|
import { range } from '@dxos/util';
|
|
12
10
|
|
|
13
11
|
import { FeedQueue } from './feed-queue';
|
|
@@ -69,44 +67,6 @@ describe('FeedQueue', () => {
|
|
|
69
67
|
expect(queue.feed.properties.closed).to.be.false;
|
|
70
68
|
});
|
|
71
69
|
|
|
72
|
-
test('works with webfs', async () => {
|
|
73
|
-
const localBuilder = builder.clone().setStorage(createStorage({ type: StorageType.WEBFS }));
|
|
74
|
-
const feedStore = localBuilder.createFeedStore();
|
|
75
|
-
const key = await localBuilder.keyring.createKey();
|
|
76
|
-
const feed = await feedStore.openFeed(key, { writable: true });
|
|
77
|
-
|
|
78
|
-
const queue = new FeedQueue<any>(feed);
|
|
79
|
-
await queue.open();
|
|
80
|
-
|
|
81
|
-
expect(queue.isOpen).to.be.true;
|
|
82
|
-
expect(queue.feed.properties.closed).to.be.false;
|
|
83
|
-
|
|
84
|
-
// Write blocks.
|
|
85
|
-
// TODO(burdon): Write slowly to test writing close feed.
|
|
86
|
-
await localBuilder._properties.generator!.writeBlocks(feed.createFeedWriter(), { count: 10 });
|
|
87
|
-
|
|
88
|
-
// Read until queue closed (pop throws exception).
|
|
89
|
-
const errorPromise = untilError(async () => {
|
|
90
|
-
while (true) {
|
|
91
|
-
const next = await queue.pop();
|
|
92
|
-
log('next', { next: next.seq });
|
|
93
|
-
await sleep(50);
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
// Close the queue.
|
|
98
|
-
await untilPromise(async () => {
|
|
99
|
-
await sleep(400);
|
|
100
|
-
await queue.close();
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Expect pop to throw error when queue is closed.
|
|
104
|
-
await errorPromise;
|
|
105
|
-
|
|
106
|
-
expect(queue.isOpen).to.be.false;
|
|
107
|
-
expect(queue.feed.properties.closed).to.be.false;
|
|
108
|
-
}).onlyEnvironments('chromium');
|
|
109
|
-
|
|
110
70
|
test('feed closed while reading', async () => {
|
|
111
71
|
const feedStore = builder.createFeedStore();
|
|
112
72
|
const key = await builder.keyring.createKey();
|
|
@@ -145,58 +105,56 @@ describe('FeedQueue', () => {
|
|
|
145
105
|
});
|
|
146
106
|
|
|
147
107
|
// TODO(dmaretskyi): Fix.
|
|
148
|
-
test
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
108
|
+
test.skip('responds immediately when feed is appended', async () => {
|
|
109
|
+
const key = await builder.keyring.createKey();
|
|
110
|
+
const feed = await factory.createFeed(key, { writable: true });
|
|
111
|
+
await feed.open();
|
|
112
|
+
|
|
113
|
+
const queue = new FeedQueue<any>(feed);
|
|
114
|
+
await queue.open();
|
|
115
|
+
expect(queue.isOpen).to.be.true;
|
|
116
|
+
|
|
117
|
+
const numBlocks = 10;
|
|
118
|
+
const [done, received] = latch({ count: numBlocks });
|
|
119
|
+
|
|
120
|
+
{
|
|
121
|
+
// Read blocks.
|
|
122
|
+
setTimeout(async () => {
|
|
123
|
+
expect(queue.peek()).to.be.undefined;
|
|
124
|
+
expect(queue.length).to.eq(0);
|
|
125
|
+
expect(feed.properties.length).to.eq(0);
|
|
126
|
+
|
|
127
|
+
const next = await asyncTimeout(queue.pop(), 500);
|
|
128
|
+
expect(next).not.to.be.undefined;
|
|
129
|
+
received();
|
|
130
|
+
|
|
131
|
+
// Check called immediately (i.e., after first block is written).
|
|
132
|
+
expect(queue.length).to.eq(1);
|
|
133
|
+
expect(feed.properties.length).to.eq(1);
|
|
134
|
+
|
|
135
|
+
for await (const _ of Array.from(Array(numBlocks - 1))) {
|
|
136
|
+
const next = await queue.pop();
|
|
169
137
|
expect(next).not.to.be.undefined;
|
|
170
|
-
received();
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
expect(feed.properties.length).to.eq(1);
|
|
175
|
-
|
|
176
|
-
for await (const _ of Array.from(Array(numBlocks - 1))) {
|
|
177
|
-
const next = await queue.pop();
|
|
178
|
-
expect(next).not.to.be.undefined;
|
|
179
|
-
const i = received();
|
|
180
|
-
expect(i).to.eq(queue.index);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
138
|
+
const i = received();
|
|
139
|
+
expect(i).to.eq(queue.index);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
183
142
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
143
|
+
// Write blocks.
|
|
144
|
+
setTimeout(async () => {
|
|
145
|
+
await builder.generator.writeBlocks(feed.createFeedWriter(), {
|
|
146
|
+
count: numBlocks,
|
|
147
|
+
});
|
|
148
|
+
expect(feed.properties.length).to.eq(numBlocks);
|
|
149
|
+
expect(queue.length).to.eq(numBlocks);
|
|
150
|
+
}, 100); // Make sure reader waits.
|
|
151
|
+
}
|
|
193
152
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
.timeout(1000);
|
|
153
|
+
await done();
|
|
154
|
+
expect(queue.isOpen).to.be.true;
|
|
155
|
+
await queue.close();
|
|
156
|
+
expect(queue.isOpen).to.be.false;
|
|
157
|
+
});
|
|
200
158
|
|
|
201
159
|
test('peeks ahead', async () => {
|
|
202
160
|
const key = await builder.keyring.createKey();
|
|
@@ -240,7 +198,7 @@ describe('FeedQueue', () => {
|
|
|
240
198
|
await queue.close();
|
|
241
199
|
});
|
|
242
200
|
|
|
243
|
-
test('set a start sequence', async () => {
|
|
201
|
+
test('set a start sequence', { timeout: 1000 }, async () => {
|
|
244
202
|
const numBlocks = 10;
|
|
245
203
|
const start = 2;
|
|
246
204
|
|
|
@@ -273,5 +231,5 @@ describe('FeedQueue', () => {
|
|
|
273
231
|
expect(queue.isOpen).to.be.true;
|
|
274
232
|
await queue.close();
|
|
275
233
|
expect(queue.isOpen).to.be.false;
|
|
276
|
-
})
|
|
234
|
+
});
|
|
277
235
|
});
|
|
@@ -2,12 +2,11 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { expect } from '
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
6
|
|
|
7
7
|
import { latch } from '@dxos/async';
|
|
8
8
|
import { log } from '@dxos/log';
|
|
9
9
|
import { faker } from '@dxos/random';
|
|
10
|
-
import { describe, test } from '@dxos/test';
|
|
11
10
|
|
|
12
11
|
import { type FeedBlockSelector, FeedSetIterator } from './feed-set-iterator';
|
|
13
12
|
import { TestItemBuilder } from './testing';
|
|
@@ -92,7 +91,7 @@ describe('FeedSetIterator', () => {
|
|
|
92
91
|
await iterator.close();
|
|
93
92
|
});
|
|
94
93
|
|
|
95
|
-
test('reads blocks in order', async () => {
|
|
94
|
+
test('reads blocks in order', { timeout: 3000 }, async () => {
|
|
96
95
|
const builder = new TestItemBuilder();
|
|
97
96
|
const feedStore = builder.createFeedStore();
|
|
98
97
|
|
|
@@ -168,7 +167,7 @@ describe('FeedSetIterator', () => {
|
|
|
168
167
|
expect(iterator.isRunning).to.be.false;
|
|
169
168
|
await iterator.close();
|
|
170
169
|
await feedStore.close();
|
|
171
|
-
})
|
|
170
|
+
});
|
|
172
171
|
|
|
173
172
|
test('start from non-zero index', async () => {
|
|
174
173
|
const builder = new TestItemBuilder();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { describe, expect, test } from 'vitest';
|
|
6
|
+
|
|
7
|
+
import { faker } from '@dxos/random';
|
|
8
|
+
import { createStorage, StorageType } from '@dxos/random-access-storage';
|
|
9
|
+
|
|
10
|
+
import { TestItemBuilder } from './testing';
|
|
11
|
+
|
|
12
|
+
describe('FeedStore', () => {
|
|
13
|
+
test('reopens a feed and reads data from storage', async () => {
|
|
14
|
+
const builder = new TestItemBuilder();
|
|
15
|
+
const feedKey = await builder.keyring!.createKey();
|
|
16
|
+
|
|
17
|
+
const numBlocks = 10;
|
|
18
|
+
|
|
19
|
+
// NOTE: Must use Node so that data is persistent across invocations.
|
|
20
|
+
const storage = createStorage({ type: StorageType.NODE });
|
|
21
|
+
|
|
22
|
+
// Write.
|
|
23
|
+
{
|
|
24
|
+
const feedStore = builder.clone().setStorage(storage).createFeedStore();
|
|
25
|
+
const feed = await feedStore.openFeed(feedKey, { writable: true });
|
|
26
|
+
|
|
27
|
+
for (const i of Array.from(Array(numBlocks)).keys()) {
|
|
28
|
+
await feed.append({
|
|
29
|
+
id: String(i),
|
|
30
|
+
value: faker.lorem.sentence(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
expect(feed.properties.length).to.eq(numBlocks);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Read.
|
|
38
|
+
{
|
|
39
|
+
const feedStore = builder.clone().setStorage(storage).createFeedStore();
|
|
40
|
+
const feed = await feedStore.openFeed(feedKey);
|
|
41
|
+
expect(feed.properties.length).to.eq(numBlocks);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Delete.
|
|
45
|
+
{
|
|
46
|
+
await storage.reset();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Read (should be empty).
|
|
50
|
+
{
|
|
51
|
+
const feedStore = builder.clone().setStorage(storage).createFeedStore();
|
|
52
|
+
const feed = await feedStore.openFeed(feedKey);
|
|
53
|
+
expect(feed.properties.length).to.eq(0);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
});
|