@fireproof/core-test 0.23.0 → 0.23.1-dev-issue-1057
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/blockstore/interceptor-gateway.test.js.map +1 -1
- package/blockstore/keyed-crypto-indexeddb-file.test.js.map +1 -1
- package/blockstore/keyed-crypto.test.js.map +1 -1
- package/blockstore/loader.test.js.map +1 -1
- package/blockstore/standalone.test.js.map +1 -1
- package/blockstore/store.test.js.map +1 -1
- package/blockstore/transaction.test.js.map +1 -1
- package/fireproof/all-gateway.test.js.map +1 -1
- package/fireproof/attachable.test.js.map +1 -1
- package/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.js.map +1 -1
- package/fireproof/charwise-boolean.test.js.map +1 -1
- package/fireproof/compact-strategy.test.js.map +1 -1
- package/fireproof/concurrent.test.js.map +1 -1
- package/fireproof/crdt.test.js.map +1 -1
- package/fireproof/database.test.js.map +1 -1
- package/fireproof/deleted-docs-handling.test.js.map +1 -1
- package/fireproof/fireproof.test.fixture.js.map +1 -1
- package/fireproof/fireproof.test.js.map +1 -1
- package/fireproof/hello.test.js.map +1 -1
- package/fireproof/indexer.test.js.map +1 -1
- package/fireproof/multiple-ledger.test.js.map +1 -1
- package/fireproof/query-docs.test.js.map +1 -1
- package/fireproof/query-limit-issue.test.js.map +1 -1
- package/fireproof/query-property-inconsistency.test.js.map +1 -1
- package/fireproof/query-result-properties.test.js.map +1 -1
- package/fireproof/stable-cid.test.js.map +1 -1
- package/fireproof/utils.test.js.map +1 -1
- package/gateway/file/loader-config.test.js.map +1 -1
- package/gateway/indexeddb/create-db-on-write.test.js.map +1 -1
- package/gateway/indexeddb/loader-config.test.js.map +1 -1
- package/global-setup.js.map +1 -1
- package/helpers.js.map +1 -1
- package/package.json +19 -19
- package/protocols/cloud/msger.test.js.map +1 -1
- package/runtime/fp-envelope-serialize.test.js.map +1 -1
- package/runtime/key-bag.test.js.map +1 -1
- package/runtime/meta-key-hack.test.js.map +1 -1
- package/setup.file.js.map +1 -1
- package/setup.indexeddb.js.map +1 -1
- package/setup.memory.js.map +1 -1
- package/vitest.config.js.map +1 -1
- package/vitest.file.config.js.map +1 -1
- package/vitest.indexeddb.config.js.map +1 -1
- package/vitest.memory.config.js.map +1 -1
- package/blockstore/fp-envelope.test.ts-off +0 -65
- package/blockstore/fragment-gateway.test.ts-off +0 -106
- package/blockstore/interceptor-gateway.test.ts +0 -259
- package/blockstore/keyed-crypto-indexeddb-file.test.ts +0 -134
- package/blockstore/keyed-crypto.test.ts +0 -381
- package/blockstore/loader.test.ts +0 -313
- package/blockstore/standalone.test.ts +0 -156
- package/blockstore/store.test.ts +0 -199
- package/blockstore/transaction.test.ts +0 -132
- package/fireproof/all-gateway.test.ts +0 -477
- package/fireproof/attachable.test.ts +0 -677
- package/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.car +0 -0
- package/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +0 -324
- package/fireproof/charwise-boolean.test.ts +0 -68
- package/fireproof/compact-strategy.test.ts +0 -40
- package/fireproof/concurrent.test.ts +0 -37
- package/fireproof/crdt.test.ts +0 -572
- package/fireproof/database.test.ts +0 -772
- package/fireproof/deleted-docs-handling.test.ts +0 -112
- package/fireproof/fireproof.test.fixture.ts +0 -133
- package/fireproof/fireproof.test.ts +0 -767
- package/fireproof/hello.test.ts +0 -75
- package/fireproof/indexer.test.ts +0 -459
- package/fireproof/multiple-ledger.test.ts +0 -67
- package/fireproof/query-docs.test.ts +0 -117
- package/fireproof/query-limit-issue.test.ts +0 -147
- package/fireproof/query-property-inconsistency.test.ts +0 -90
- package/fireproof/query-result-properties.test.ts +0 -43
- package/fireproof/stable-cid.test.ts +0 -72
- package/fireproof/utils.test.ts +0 -137
- package/gateway/file/loader-config.test.ts +0 -309
- package/gateway/indexeddb/create-db-on-write.test.ts +0 -202
- package/gateway/indexeddb/loader-config.test.ts +0 -80
- package/global-setup.ts +0 -11
- package/helpers.ts +0 -177
- package/protocols/cloud/msger.test.ts +0 -559
- package/runtime/fp-envelope-serialize.test.ts +0 -266
- package/runtime/key-bag.test.ts +0 -243
- package/runtime/meta-key-hack.test.ts +0 -103
- package/setup.file.ts +0 -1
- package/setup.indexeddb.ts +0 -0
- package/setup.memory.ts +0 -2
- package/tsconfig.json +0 -18
- package/vitest.config.ts +0 -8
- package/vitest.file.config.ts +0 -11
- package/vitest.indexeddb.config.ts +0 -34
- package/vitest.memory.config.ts +0 -24
|
@@ -1,677 +0,0 @@
|
|
|
1
|
-
import { AppContext, BuildURI, URI, WithoutPromise } from "@adviser/cement";
|
|
2
|
-
import { stripper } from "@adviser/cement/utils";
|
|
3
|
-
import { Attachable, Database, fireproof, GatewayUrlsParam, PARAM, Attached, TraceFn } from "@fireproof/core";
|
|
4
|
-
import { CarReader } from "@ipld/car/reader";
|
|
5
|
-
import * as dagCbor from "@ipld/dag-cbor";
|
|
6
|
-
import { mockLoader } from "../helpers.js";
|
|
7
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
8
|
-
import { ensureSuperThis, sleep } from "@fireproof/core-runtime";
|
|
9
|
-
import { DefSerdeGateway } from "@fireproof/core-gateways-base";
|
|
10
|
-
import { MemoryGateway } from "@fireproof/core-gateways-memory";
|
|
11
|
-
import { AttachedRemotesImpl } from "@fireproof/core-blockstore";
|
|
12
|
-
import { AttachedStores } from "@fireproof/core-types-blockstore";
|
|
13
|
-
|
|
14
|
-
const ROWS = 1;
|
|
15
|
-
|
|
16
|
-
class AJoinable implements Attachable {
|
|
17
|
-
readonly name: string;
|
|
18
|
-
readonly db: Database;
|
|
19
|
-
|
|
20
|
-
constructor(name: string, db: Database) {
|
|
21
|
-
this.name = name;
|
|
22
|
-
this.db = db;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
async configHash() {
|
|
26
|
-
return `joinable-${this.name}`;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
prepare(): Promise<GatewayUrlsParam> {
|
|
30
|
-
return Promise.resolve({
|
|
31
|
-
car: {
|
|
32
|
-
url: BuildURI.from(`memory://car/${this.name}`)
|
|
33
|
-
.setParam(PARAM.STORE_KEY, this.db.ledger.opts.storeUrls.data.car.getParam(PARAM.STORE_KEY, "@fireproof:attach@"))
|
|
34
|
-
.setParam(PARAM.SELF_REFLECT, "x"),
|
|
35
|
-
},
|
|
36
|
-
meta: {
|
|
37
|
-
url: BuildURI.from(`memory://meta/${this.name}`)
|
|
38
|
-
.setParam(PARAM.STORE_KEY, this.db.ledger.opts.storeUrls.data.meta.getParam(PARAM.STORE_KEY, "@fireproof:attach@"))
|
|
39
|
-
.setParam(PARAM.SELF_REFLECT, "x"),
|
|
40
|
-
},
|
|
41
|
-
file: {
|
|
42
|
-
url: BuildURI.from(`memory://file/${this.name}`)
|
|
43
|
-
.setParam(PARAM.STORE_KEY, this.db.ledger.opts.storeUrls.data.file.getParam(PARAM.STORE_KEY, "@fireproof:attach@"))
|
|
44
|
-
.setParam(PARAM.SELF_REFLECT, "x"),
|
|
45
|
-
},
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function aJoinable(name: string, db: Database): Attachable {
|
|
51
|
-
return new AJoinable(name, db);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function attachableStoreUrls(name: string, db: Database) {
|
|
55
|
-
return {
|
|
56
|
-
// base: `memory://${name}`,
|
|
57
|
-
data: {
|
|
58
|
-
car: BuildURI.from(`memory://car/${name}?`)
|
|
59
|
-
.setParam(PARAM.STORE_KEY, db.ledger.opts.storeUrls.data.car.getParam(PARAM.STORE_KEY, ""))
|
|
60
|
-
.URI(),
|
|
61
|
-
meta: BuildURI.from(`memory://meta/${name}`)
|
|
62
|
-
.setParam(PARAM.STORE_KEY, db.ledger.opts.storeUrls.data.meta.getParam(PARAM.STORE_KEY, ""))
|
|
63
|
-
.URI(),
|
|
64
|
-
file: BuildURI.from(`memory://file/${name}`)
|
|
65
|
-
.setParam(PARAM.STORE_KEY, db.ledger.opts.storeUrls.data.file.getParam(PARAM.STORE_KEY, ""))
|
|
66
|
-
.URI(),
|
|
67
|
-
wal: BuildURI.from(`memory://wal/${name}`)
|
|
68
|
-
.setParam(PARAM.STORE_KEY, db.ledger.opts.storeUrls.data.wal.getParam(PARAM.STORE_KEY, ""))
|
|
69
|
-
.URI(),
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
describe("meta check", () => {
|
|
75
|
-
const sthis = ensureSuperThis();
|
|
76
|
-
it("empty Database", async () => {
|
|
77
|
-
const name = `remote-db-${sthis.nextId().str}`;
|
|
78
|
-
const db = fireproof(name, {
|
|
79
|
-
storeUrls: {
|
|
80
|
-
base: `memory://${name}`,
|
|
81
|
-
},
|
|
82
|
-
});
|
|
83
|
-
await db.ready();
|
|
84
|
-
const gws = db.ledger.crdt.blockstore.loader.attachedStores.local();
|
|
85
|
-
await db.close();
|
|
86
|
-
expect(
|
|
87
|
-
Array.from(((gws.active.car.realGateway as DefSerdeGateway).gw as MemoryGateway).memories.entries()).filter(([k]) =>
|
|
88
|
-
k.startsWith(`memory://${name}`),
|
|
89
|
-
),
|
|
90
|
-
).toEqual([]);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it("one record Database", async () => {
|
|
94
|
-
const name = `remote-db-${sthis.nextId().str}`;
|
|
95
|
-
const db = fireproof(name, {
|
|
96
|
-
storeUrls: {
|
|
97
|
-
base: `memory://${name}`,
|
|
98
|
-
},
|
|
99
|
-
});
|
|
100
|
-
await db.put({ _id: `id-${0}`, value: `value-${0}` });
|
|
101
|
-
await db.close();
|
|
102
|
-
|
|
103
|
-
const db1 = fireproof(name, {
|
|
104
|
-
storeUrls: {
|
|
105
|
-
base: `memory://${name}`,
|
|
106
|
-
},
|
|
107
|
-
});
|
|
108
|
-
await db1.close();
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("multiple record Database", async () => {
|
|
112
|
-
const name = `remote-db-${sthis.nextId().str}`;
|
|
113
|
-
const base = `memory://${name}?storekey=insecure`;
|
|
114
|
-
const db = fireproof(name, {
|
|
115
|
-
storeUrls: {
|
|
116
|
-
base,
|
|
117
|
-
},
|
|
118
|
-
});
|
|
119
|
-
await db.ready();
|
|
120
|
-
await db.put({ _id: `id-${0}`, value: `value-${0}` });
|
|
121
|
-
const gws = db.ledger.crdt.blockstore.loader.attachedStores.local();
|
|
122
|
-
expect(db.ledger.crdt.blockstore.loader.carLog.asArray().map((i) => i.map((i) => i.toString()))).toEqual([
|
|
123
|
-
["baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e"],
|
|
124
|
-
["baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu"],
|
|
125
|
-
]);
|
|
126
|
-
await db.close();
|
|
127
|
-
expect(
|
|
128
|
-
Array.from(((gws.active.car.realGateway as DefSerdeGateway).gw as MemoryGateway).memories.entries())
|
|
129
|
-
.filter(([k]) => k.startsWith(`memory://${name}`))
|
|
130
|
-
.map(([k]) =>
|
|
131
|
-
stripper(
|
|
132
|
-
["name", "storekey", "version"],
|
|
133
|
-
Array.from(URI.from(k).getParams).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}),
|
|
134
|
-
),
|
|
135
|
-
),
|
|
136
|
-
).toEqual([
|
|
137
|
-
{
|
|
138
|
-
key: "baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu",
|
|
139
|
-
store: "car",
|
|
140
|
-
suffix: ".car",
|
|
141
|
-
},
|
|
142
|
-
{
|
|
143
|
-
key: "main",
|
|
144
|
-
store: "wal",
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
key: "main",
|
|
148
|
-
store: "meta",
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
key: "baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e",
|
|
152
|
-
store: "car",
|
|
153
|
-
suffix: ".car",
|
|
154
|
-
},
|
|
155
|
-
]);
|
|
156
|
-
|
|
157
|
-
const db1 = fireproof(name, {
|
|
158
|
-
storeUrls: {
|
|
159
|
-
base,
|
|
160
|
-
},
|
|
161
|
-
});
|
|
162
|
-
expect(db1.ledger).not.equal(db.ledger);
|
|
163
|
-
await db1.ready();
|
|
164
|
-
expect(db1.ledger.crdt.blockstore.loader.carLog.asArray().map((i) => i.map((i) => i.toString()))).toEqual([
|
|
165
|
-
["baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e"],
|
|
166
|
-
["baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu"],
|
|
167
|
-
]);
|
|
168
|
-
|
|
169
|
-
const gensis = await db1.get(PARAM.GENESIS_CID);
|
|
170
|
-
expect(gensis).toEqual({ _id: PARAM.GENESIS_CID });
|
|
171
|
-
|
|
172
|
-
const val = await db1.allDocs();
|
|
173
|
-
expect(val.rows).toEqual([
|
|
174
|
-
{
|
|
175
|
-
key: "id-0",
|
|
176
|
-
value: {
|
|
177
|
-
_id: "id-0",
|
|
178
|
-
value: "value-0",
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
]);
|
|
182
|
-
const car = Array.from(((gws.active.car.realGateway as DefSerdeGateway).gw as MemoryGateway).memories.entries())
|
|
183
|
-
.filter(([k]) => k.startsWith(`memory://${name}`))
|
|
184
|
-
.map(([k, v]) => [URI.from(k).getParam(PARAM.KEY), v])
|
|
185
|
-
.find(([k]) => k === "baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu") as [string, Uint8Array];
|
|
186
|
-
const rawReader = await CarReader.fromBytes(car[1]);
|
|
187
|
-
const blocks = [];
|
|
188
|
-
for await (const block of rawReader.blocks()) {
|
|
189
|
-
blocks.push(block);
|
|
190
|
-
}
|
|
191
|
-
expect(dagCbor.decode(blocks[1].bytes)).toEqual({
|
|
192
|
-
doc: {
|
|
193
|
-
_id: "baembeiarootfireproofgenesisblockaaaafireproofgenesisblocka",
|
|
194
|
-
},
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
expect(blocks.map((i) => i.cid.toString())).toEqual([
|
|
198
|
-
"bafyreibxibqhi6wh5klrje7ne4htffeqyyqfd6y7x2no6wnhid4nixizau",
|
|
199
|
-
"bafyreidnvv4mwvweup5w52ddre2sl4syhvczm6ejqsmuekajowdl2cf2q4",
|
|
200
|
-
"bafyreihh6nbfbhgkf5lz7hhsscjgiquw426rxzr3fprbgonekzmyvirrhe",
|
|
201
|
-
"bafyreiejg3twlaxr7gfvvhtxrhvwaydytdv4guidmtvaz5dskm6gp73ryi",
|
|
202
|
-
"bafyreiblui55o25dopc5faol3umsnuohb5carto7tot4kicnkfc37he4h4",
|
|
203
|
-
]);
|
|
204
|
-
});
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
describe("activate store", () => {
|
|
208
|
-
// activate(store: DataAndMetaStore | CoerceURI): ActiveStore {
|
|
209
|
-
// if (isCoerceURI(store)) {
|
|
210
|
-
// throw this.loadable.sthis.logger.Error().Msg("store must be an object").AsError();
|
|
211
|
-
// }
|
|
212
|
-
// return new ActiveStoreImpl(store as DataAndMetaStore, this);
|
|
213
|
-
// }
|
|
214
|
-
|
|
215
|
-
const sthis = ensureSuperThis();
|
|
216
|
-
let attach: AttachedStores;
|
|
217
|
-
let firstAttached: Attached;
|
|
218
|
-
let secondAttached: Attached;
|
|
219
|
-
beforeEach(async () => {
|
|
220
|
-
attach = new AttachedRemotesImpl(mockLoader(sthis));
|
|
221
|
-
firstAttached = await attach.attach(
|
|
222
|
-
{
|
|
223
|
-
name: "first",
|
|
224
|
-
configHash: async () => "first",
|
|
225
|
-
prepare: async () => ({
|
|
226
|
-
car: { url: "memory://first?store=car" },
|
|
227
|
-
meta: { url: "memory://first?store=meta" },
|
|
228
|
-
file: { url: "memory://first" },
|
|
229
|
-
wal: { url: "memory://first?store=wal" },
|
|
230
|
-
}),
|
|
231
|
-
},
|
|
232
|
-
(at) => Promise.resolve(at),
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
secondAttached = await attach.attach(
|
|
236
|
-
{
|
|
237
|
-
name: "second",
|
|
238
|
-
configHash: async () => "second",
|
|
239
|
-
prepare: async () => ({
|
|
240
|
-
car: { url: "memory://second?store=car" },
|
|
241
|
-
meta: { url: "memory://second?store=meta" },
|
|
242
|
-
file: { url: "memory://second?store=file" },
|
|
243
|
-
}),
|
|
244
|
-
},
|
|
245
|
-
(at) => Promise.resolve(at),
|
|
246
|
-
);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it("activate by store", async () => {
|
|
250
|
-
expect(attach.activate(secondAttached.stores).active.car.url().toString()).toBe(
|
|
251
|
-
"memory://second?localName=first&name=second&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
|
252
|
-
);
|
|
253
|
-
expect(attach.activate(firstAttached.stores).local().active.car.url().toString()).toBe(
|
|
254
|
-
"memory://first?name=first&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
|
255
|
-
);
|
|
256
|
-
expect(attach.activate(firstAttached.stores).active.meta.url().toString()).toBe(
|
|
257
|
-
"memory://first?name=first&store=meta&storekey=%40first-meta%40&version=v0.19-memory",
|
|
258
|
-
);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it("activate by store", async () => {
|
|
262
|
-
expect(attach.activate("memory://second").active.car.url().toString()).toBe(
|
|
263
|
-
"memory://second?localName=first&name=second&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
|
264
|
-
);
|
|
265
|
-
expect(attach.activate("memory://second").remotes()[0].active.car.url().toString()).toEqual(
|
|
266
|
-
"memory://second?localName=first&name=second&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
|
267
|
-
);
|
|
268
|
-
expect(attach.activate("memory://first?store=meta").active.car.url().toString()).toBe(
|
|
269
|
-
"memory://first?name=first&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
|
270
|
-
);
|
|
271
|
-
});
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
describe("join function", () => {
|
|
275
|
-
const sthis = ensureSuperThis();
|
|
276
|
-
// export const connect: ConnectFunction = (
|
|
277
|
-
// db: Database,
|
|
278
|
-
// remoteDbName = "",
|
|
279
|
-
// url = "netlify://localhost:8888?protocol=ws"
|
|
280
|
-
// ) => {
|
|
281
|
-
// const { sthis, name: dbName } = db;
|
|
282
|
-
// if (!dbName) {
|
|
283
|
-
// throw new Error("dbName is required");
|
|
284
|
-
// }
|
|
285
|
-
// const urlObj = BuildURI.from(url);
|
|
286
|
-
// const existingName = urlObj.getParam("name");
|
|
287
|
-
// urlObj.defParam("name", remoteDbName || existingName || dbName);
|
|
288
|
-
// urlObj.defParam("localName", dbName);
|
|
289
|
-
// urlObj.defParam("storekey", `@${dbName}:data@`);
|
|
290
|
-
// return connectionCache.get(urlObj.toString()).once(() => {
|
|
291
|
-
// makeKeyBagUrlExtractable(sthis);
|
|
292
|
-
// const connection = connectionFactory(sthis, urlObj);
|
|
293
|
-
// connection.connect(db.ledger.crdt.blockstore);
|
|
294
|
-
// return connection;
|
|
295
|
-
// });
|
|
296
|
-
// };
|
|
297
|
-
|
|
298
|
-
let db: Database;
|
|
299
|
-
let joinableDBs: string[] = [];
|
|
300
|
-
beforeEach(async () => {
|
|
301
|
-
const set = sthis.nextId().str;
|
|
302
|
-
|
|
303
|
-
db = fireproof(`db-${set}`, {
|
|
304
|
-
storeUrls: {
|
|
305
|
-
base: `memory://db-${set}`,
|
|
306
|
-
},
|
|
307
|
-
});
|
|
308
|
-
// await db.put({ _id: `genesis`, value: `genesis` });
|
|
309
|
-
for (let j = 0; j < ROWS; j++) {
|
|
310
|
-
await db.put({ _id: `db-${j}`, value: `db-${set}` });
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
joinableDBs = await Promise.all(
|
|
314
|
-
new Array(1).fill(1).map(async (_, i) => {
|
|
315
|
-
const name = `remote-db-${i}-${set}`;
|
|
316
|
-
const jdb = fireproof(name, {
|
|
317
|
-
storeUrls: attachableStoreUrls(name, db),
|
|
318
|
-
});
|
|
319
|
-
// await db.put({ _id: `genesis`, value: `genesis` });
|
|
320
|
-
// await db.ready();
|
|
321
|
-
for (let j = 0; j < ROWS; j++) {
|
|
322
|
-
await jdb.put({ _id: `${i}-${j}`, value: `${i}-${j}` });
|
|
323
|
-
}
|
|
324
|
-
expect(await jdb.get(PARAM.GENESIS_CID)).toEqual({ _id: PARAM.GENESIS_CID });
|
|
325
|
-
await jdb.close();
|
|
326
|
-
return name;
|
|
327
|
-
}),
|
|
328
|
-
);
|
|
329
|
-
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
330
|
-
|
|
331
|
-
expect(await db.get(PARAM.GENESIS_CID)).toEqual({ _id: PARAM.GENESIS_CID });
|
|
332
|
-
});
|
|
333
|
-
afterEach(async () => {
|
|
334
|
-
await db.close();
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it("it is joinable detachable", async () => {
|
|
338
|
-
const my = fireproof("my", {
|
|
339
|
-
storeUrls: {
|
|
340
|
-
base: BuildURI.from("memory://it-is-joinable-detachable").setParam(
|
|
341
|
-
PARAM.STORE_KEY,
|
|
342
|
-
db.ledger.opts.storeUrls.data.car.getParam(PARAM.STORE_KEY, ""),
|
|
343
|
-
), // .setParam(PARAM.STORE_KEY, "@fireproof:attach@"),
|
|
344
|
-
},
|
|
345
|
-
});
|
|
346
|
-
await my.put({ _id: "genesis", value: "genesis" });
|
|
347
|
-
await Promise.all(
|
|
348
|
-
joinableDBs.map(async (name) => {
|
|
349
|
-
const tmp = fireproof(name, {
|
|
350
|
-
storeUrls: attachableStoreUrls(name, my),
|
|
351
|
-
});
|
|
352
|
-
const res = await tmp.allDocs();
|
|
353
|
-
expect(res.rows.length).toBe(ROWS);
|
|
354
|
-
await tmp.close();
|
|
355
|
-
const attached = await my.attach(aJoinable(name, my));
|
|
356
|
-
expect(attached).toBeDefined();
|
|
357
|
-
}),
|
|
358
|
-
);
|
|
359
|
-
expect(my.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
|
360
|
-
await my.close();
|
|
361
|
-
expect(my.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(0);
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
it("it is inbound syncing", async () => {
|
|
365
|
-
await Promise.all(
|
|
366
|
-
joinableDBs.map(async (name) => {
|
|
367
|
-
const attached = await db.attach(aJoinable(name, db));
|
|
368
|
-
expect(attached).toBeDefined();
|
|
369
|
-
}),
|
|
370
|
-
);
|
|
371
|
-
await sleep(100);
|
|
372
|
-
expect(db.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
|
373
|
-
const res = await db.allDocs();
|
|
374
|
-
expect(res.rows.length).toBe(ROWS + ROWS * joinableDBs.length);
|
|
375
|
-
});
|
|
376
|
-
|
|
377
|
-
it("it empty inbound syncing", async () => {
|
|
378
|
-
const name = `empty-db-${sthis.nextId().str}`;
|
|
379
|
-
const mydb = fireproof(name, {
|
|
380
|
-
storeUrls: attachableStoreUrls(name, db),
|
|
381
|
-
});
|
|
382
|
-
await Promise.all(
|
|
383
|
-
joinableDBs.map(async (name) => {
|
|
384
|
-
const attached = await mydb.attach(aJoinable(name, mydb));
|
|
385
|
-
expect(attached).toBeDefined();
|
|
386
|
-
}),
|
|
387
|
-
);
|
|
388
|
-
await sleep(100);
|
|
389
|
-
expect(mydb.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
|
390
|
-
const res = await mydb.allDocs();
|
|
391
|
-
expect(res.rows.length).toBe(ROWS * joinableDBs.length);
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
it("prepare only once", async () => {
|
|
395
|
-
const db = fireproof(`db-${sthis.nextId().str}`, {
|
|
396
|
-
storeUrls: {
|
|
397
|
-
base: `memory://prepare`,
|
|
398
|
-
},
|
|
399
|
-
});
|
|
400
|
-
const mocked = aJoinable("test", db);
|
|
401
|
-
const originalPrepare = mocked.prepare;
|
|
402
|
-
mocked.prepare = vi.fn(() => originalPrepare.apply(mocked));
|
|
403
|
-
expect(mocked.prepare).not.toHaveBeenCalled();
|
|
404
|
-
for (let i = 0; i < 10; i++) {
|
|
405
|
-
await db.attach(mocked);
|
|
406
|
-
expect(mocked.prepare).toHaveBeenCalled();
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
it("offline sync", async () => {
|
|
411
|
-
const id = sthis.nextId().str;
|
|
412
|
-
// console.log("sync-offline");
|
|
413
|
-
|
|
414
|
-
// console.log("outbound-db");
|
|
415
|
-
// console.log("-1");
|
|
416
|
-
const poutbound = await prepareDb(`outbound-db-${id}`, "memory://sync-outbound");
|
|
417
|
-
// console.log("-2");
|
|
418
|
-
await poutbound.db.attach(aJoinable(`sync-${id}`, poutbound.db));
|
|
419
|
-
await poutbound.db.close();
|
|
420
|
-
// console.log("-3");
|
|
421
|
-
const outRows = await readDb(`outbound-db-${id}`, "memory://sync-outbound");
|
|
422
|
-
|
|
423
|
-
expect(outRows.length).toBe(ROWS);
|
|
424
|
-
|
|
425
|
-
const pinbound = await prepareDb(`inbound-db-${id}`, `memory://sync-inbound`);
|
|
426
|
-
await pinbound.db.close();
|
|
427
|
-
const inRows = await readDb(`inbound-db-${id}`, "memory://sync-inbound");
|
|
428
|
-
|
|
429
|
-
expect(inRows.length).toBe(ROWS);
|
|
430
|
-
|
|
431
|
-
const inbound = await syncDb(`inbound-db-${id}`, `memory://sync-inbound`);
|
|
432
|
-
await inbound.attach(aJoinable(`sync-${id}`, inbound));
|
|
433
|
-
await inbound.close();
|
|
434
|
-
|
|
435
|
-
// console.log("result");
|
|
436
|
-
const resultRows = await readDb(`inbound-db-${id}`, "memory://sync-inbound");
|
|
437
|
-
// console.log(re);
|
|
438
|
-
// console.log(inRows);
|
|
439
|
-
expect(resultRows.length).toBe(ROWS * 2);
|
|
440
|
-
expect(resultRows).toEqual(outRows.concat(inRows).sort((a, b) => a.key.localeCompare(b.key)));
|
|
441
|
-
|
|
442
|
-
const joined = { db: await syncDb(`joined-db-${id}`, "memory://sync-joined") };
|
|
443
|
-
await joined.db.attach(aJoinable(`sync-${id}`, joined.db));
|
|
444
|
-
await joined.db.close();
|
|
445
|
-
const joinedRows = await readDb(`joined-db-${id}`, "memory://sync-joined");
|
|
446
|
-
expect(resultRows).toEqual(joinedRows);
|
|
447
|
-
}, 100_000);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
// interface WaitItem {
|
|
451
|
-
// ev: IdleEventFromBlockstore | BusyEventFromBlockstore;
|
|
452
|
-
// waitforIdle: Set<Future<IdleEventFromBlockstore>>;
|
|
453
|
-
// }
|
|
454
|
-
// class WaitIdle {
|
|
455
|
-
// readonly _waitState = new Map<string, WaitItem>();
|
|
456
|
-
//
|
|
457
|
-
// upsertItem(name: string) {
|
|
458
|
-
// let item = this._waitState.get(name);
|
|
459
|
-
// if (!item) {
|
|
460
|
-
// item = { ev: {} as IdleEventFromBlockstore, waitforIdle: new Set() };
|
|
461
|
-
// this._waitState.set(name, item);
|
|
462
|
-
// }
|
|
463
|
-
// return item;
|
|
464
|
-
// }
|
|
465
|
-
// upsertEvent(name: string, ev: IdleEventFromBlockstore | BusyEventFromBlockstore) {
|
|
466
|
-
// this.upsertItem(name).ev = ev;
|
|
467
|
-
// }
|
|
468
|
-
//
|
|
469
|
-
// readonly _traceFn = (ev: TraceEvent) => {
|
|
470
|
-
// console.log("trace", ev.event);
|
|
471
|
-
// if (EventIsIdleFromBlockstore(ev) && ev.ledger) {
|
|
472
|
-
// const item = this.upsertItem(ev.ledger.name);
|
|
473
|
-
// item.ev = ev;
|
|
474
|
-
// console.log("database is now idle", ev.ledger.name);
|
|
475
|
-
// Array.from(item.waitforIdle).forEach((waiter) => {
|
|
476
|
-
// waiter.resolve(ev);
|
|
477
|
-
// item.waitforIdle.delete(waiter);
|
|
478
|
-
// });
|
|
479
|
-
// }
|
|
480
|
-
// if (EventIsBusyFromBlockstore(ev) && ev.ledger) {
|
|
481
|
-
// this.upsertEvent(ev.ledger.name, ev);
|
|
482
|
-
// }
|
|
483
|
-
// };
|
|
484
|
-
//
|
|
485
|
-
// traceFn(): TraceFn {
|
|
486
|
-
// return this._traceFn;
|
|
487
|
-
// }
|
|
488
|
-
//
|
|
489
|
-
// async wait(dbs: Database[]) {
|
|
490
|
-
// const waiting = dbs.map((db) => {
|
|
491
|
-
// const item = this.upsertItem(db.name);
|
|
492
|
-
// let waiter: Promise<IdleEventFromBlockstore>;
|
|
493
|
-
// if (EventIsIdleFromBlockstore(item.ev)) {
|
|
494
|
-
// console.log("database is already idle", db.name);
|
|
495
|
-
// waiter = Promise.resolve(item.ev);
|
|
496
|
-
// } else {
|
|
497
|
-
// const future = new Future<IdleEventFromBlockstore>();
|
|
498
|
-
// item.waitforIdle.add(future);
|
|
499
|
-
// waiter = future.asPromise();
|
|
500
|
-
// }
|
|
501
|
-
// return waiter;
|
|
502
|
-
// });
|
|
503
|
-
// console.log(dbs.map((db) => db.name));
|
|
504
|
-
// await Promise.all(waiting);
|
|
505
|
-
// }
|
|
506
|
-
// }
|
|
507
|
-
|
|
508
|
-
describe("sync", () => {
|
|
509
|
-
const sthis = ensureSuperThis();
|
|
510
|
-
it("online sync", async () => {
|
|
511
|
-
const id = sthis.nextId().str;
|
|
512
|
-
// const waitIdle = new WaitIdle();
|
|
513
|
-
const dbs = await Promise.all(
|
|
514
|
-
Array(3)
|
|
515
|
-
.fill(0)
|
|
516
|
-
.map(async (_, i) => {
|
|
517
|
-
const tdb = await prepareDb(`online-db-${id}-${i}`, `memory://local-${id}-${i}`);
|
|
518
|
-
await tdb.db.attach(aJoinable(`sync-${id}`, tdb.db));
|
|
519
|
-
return tdb;
|
|
520
|
-
}),
|
|
521
|
-
);
|
|
522
|
-
|
|
523
|
-
// await waitIdle.wait(dbs);
|
|
524
|
-
await sleep(1000);
|
|
525
|
-
await Promise.all(
|
|
526
|
-
dbs.map(async (tdb) => {
|
|
527
|
-
const rows = await tdb.db.allDocs();
|
|
528
|
-
// console.log(db.name, rows.rows.length);
|
|
529
|
-
// console.log(rows.rows.length);
|
|
530
|
-
expect(rows.rows.length).toBe(ROWS * dbs.length);
|
|
531
|
-
}),
|
|
532
|
-
);
|
|
533
|
-
|
|
534
|
-
const keys = (
|
|
535
|
-
await Promise.all(
|
|
536
|
-
dbs.map(async (db) => {
|
|
537
|
-
await sleep(100 * Math.random());
|
|
538
|
-
return writeRow(db, "add-online");
|
|
539
|
-
}),
|
|
540
|
-
)
|
|
541
|
-
).flat();
|
|
542
|
-
await sleep(1000);
|
|
543
|
-
await Promise.all(
|
|
544
|
-
dbs.map(async (db) => {
|
|
545
|
-
for (const key of keys) {
|
|
546
|
-
const rows = await db.db.get(key);
|
|
547
|
-
expect(rows).toEqual({ _id: key, value: key });
|
|
548
|
-
}
|
|
549
|
-
}),
|
|
550
|
-
);
|
|
551
|
-
|
|
552
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
553
|
-
const toCloseDbs = [dbs.shift()!, dbs.pop()!];
|
|
554
|
-
await Promise.all(toCloseDbs.map((tdb) => tdb.db.close()));
|
|
555
|
-
|
|
556
|
-
await Promise.all(
|
|
557
|
-
dbs.map(async (db) => {
|
|
558
|
-
return writeRow(db, "mid-dbs");
|
|
559
|
-
}),
|
|
560
|
-
);
|
|
561
|
-
|
|
562
|
-
const reOpenedWithoutAttach = await Promise.all(
|
|
563
|
-
toCloseDbs.map(async (tdb) => {
|
|
564
|
-
// console.log("reopen", tdb.db.name, tdb.db.ledger.ctx.get("base"));
|
|
565
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
566
|
-
const db = await syncDb(tdb.db.name, tdb.db.ledger.ctx.get("base")!);
|
|
567
|
-
return { db, dbId: tdb.dbId };
|
|
568
|
-
}),
|
|
569
|
-
);
|
|
570
|
-
|
|
571
|
-
// const reOpenKeys = (
|
|
572
|
-
await Promise.all(
|
|
573
|
-
dbs.map(async (db) => {
|
|
574
|
-
return writeRow(db, "reOpenKeys");
|
|
575
|
-
}),
|
|
576
|
-
);
|
|
577
|
-
// ).flat();
|
|
578
|
-
|
|
579
|
-
await Promise.all(
|
|
580
|
-
reOpenedWithoutAttach.map(async (tdb) => {
|
|
581
|
-
await tdb.db.attach(aJoinable(`sync-${id}`, tdb.db));
|
|
582
|
-
}),
|
|
583
|
-
);
|
|
584
|
-
await sleep(500);
|
|
585
|
-
|
|
586
|
-
await Promise.all(
|
|
587
|
-
dbs.map(async (tdb) => {
|
|
588
|
-
const rows = await tdb.db.allDocs();
|
|
589
|
-
// console.log(db.name, rows.rows.length);
|
|
590
|
-
// console.log(rows.rows.length);
|
|
591
|
-
expect(rows.rows.length).toBe(8 * ROWS * dbs.length);
|
|
592
|
-
}),
|
|
593
|
-
);
|
|
594
|
-
|
|
595
|
-
await Promise.all(dbs.map((tdb) => tdb.db.close()));
|
|
596
|
-
await Promise.all(reOpenedWithoutAttach.map((tdb) => tdb.db.close()));
|
|
597
|
-
}, 100_000);
|
|
598
|
-
|
|
599
|
-
it.skip("sync outbound", async () => {
|
|
600
|
-
const id = sthis.nextId().str;
|
|
601
|
-
|
|
602
|
-
const outbound = await prepareDb(`outbound-db-${id}`, `memory://sync-outbound-${id}`);
|
|
603
|
-
await outbound.db.attach(aJoinable(`sync-${id}`, outbound.db));
|
|
604
|
-
await writeRow(outbound, "outbound");
|
|
605
|
-
|
|
606
|
-
const inbound = await prepareDb(`inbound-db-${id}`, `memory://sync-inbound-${id}`);
|
|
607
|
-
await inbound.db.attach(aJoinable(`sync-${id}`, inbound.db));
|
|
608
|
-
await writeRow(inbound, "both-inbound");
|
|
609
|
-
await writeRow(outbound, "both-outbound");
|
|
610
|
-
await sleep(1000);
|
|
611
|
-
await inbound.db.close();
|
|
612
|
-
await outbound.db.close();
|
|
613
|
-
|
|
614
|
-
const inRows = await readDb(`inbound-db-${id}`, `memory://sync-inbound-${id}`);
|
|
615
|
-
const outRows = await readDb(`outbound-db-${id}`, `memory://sync-outbound-${id}`);
|
|
616
|
-
// eslint-disable-next-line no-console
|
|
617
|
-
console.log(
|
|
618
|
-
"out",
|
|
619
|
-
outRows.map((row) => row.key),
|
|
620
|
-
);
|
|
621
|
-
// eslint-disable-next-line no-console
|
|
622
|
-
console.log(
|
|
623
|
-
"in",
|
|
624
|
-
inRows.map((row) => row.key),
|
|
625
|
-
);
|
|
626
|
-
expect(inRows).toEqual(outRows);
|
|
627
|
-
}, 100_000);
|
|
628
|
-
});
|
|
629
|
-
|
|
630
|
-
async function syncDb(name: string, base: string, tracer?: TraceFn) {
|
|
631
|
-
const db = fireproof(name, {
|
|
632
|
-
storeUrls: {
|
|
633
|
-
base: BuildURI.from(base).setParam(PARAM.STORE_KEY, "@fireproof:attach@"), // .setParam(PARAM.SELF_REFLECT, "yes"),
|
|
634
|
-
},
|
|
635
|
-
ctx: AppContext.merge({ base }),
|
|
636
|
-
tracer,
|
|
637
|
-
});
|
|
638
|
-
await db.ready();
|
|
639
|
-
return db;
|
|
640
|
-
}
|
|
641
|
-
|
|
642
|
-
async function prepareDb(name: string, base: string, tracer?: TraceFn) {
|
|
643
|
-
{
|
|
644
|
-
const db = await syncDb(name, base, tracer);
|
|
645
|
-
await db.ready();
|
|
646
|
-
const dbId = await db.ledger.crdt.blockstore.loader.attachedStores.local().active.car.id();
|
|
647
|
-
const ret = { db, dbId };
|
|
648
|
-
await writeRow(ret, `initial`);
|
|
649
|
-
await db.close();
|
|
650
|
-
}
|
|
651
|
-
|
|
652
|
-
const db = await syncDb(name, base);
|
|
653
|
-
await db.ready();
|
|
654
|
-
const dbId = await db.ledger.crdt.blockstore.loader.attachedStores.local().active.car.id();
|
|
655
|
-
// const ret = { db, dbId };
|
|
656
|
-
return { db, dbId };
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
async function readDb(name: string, base: string) {
|
|
660
|
-
const db = await syncDb(name, base);
|
|
661
|
-
const rows = await db.allDocs();
|
|
662
|
-
await db.close();
|
|
663
|
-
return rows.rows.sort((a, b) => a.key.localeCompare(b.key));
|
|
664
|
-
}
|
|
665
|
-
|
|
666
|
-
async function writeRow(pdb: WithoutPromise<ReturnType<typeof prepareDb>>, style: string) {
|
|
667
|
-
return await Promise.all(
|
|
668
|
-
Array(ROWS)
|
|
669
|
-
.fill(0)
|
|
670
|
-
.map(async (_, i) => {
|
|
671
|
-
const key = `${pdb.dbId}-${pdb.db.name}-${style}-${i}`;
|
|
672
|
-
// console.log(key);
|
|
673
|
-
await pdb.db.put({ _id: key, value: key });
|
|
674
|
-
return key;
|
|
675
|
-
}),
|
|
676
|
-
);
|
|
677
|
-
}
|