peerbit 1.0.5 → 1.1.0
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/lib/esm/peer.d.ts +4 -0
- package/lib/esm/peer.js +72 -54
- package/lib/esm/peer.js.map +1 -1
- package/package.json +3 -3
- package/src/peer.ts +83 -63
package/lib/esm/peer.d.ts
CHANGED
|
@@ -22,8 +22,10 @@ export type CreateInstanceOptions = {
|
|
|
22
22
|
directory?: string;
|
|
23
23
|
cache?: LazyLevel;
|
|
24
24
|
} & OptionalCreateOptions;
|
|
25
|
+
type ProgramMergeStrategy = "replace" | "reject";
|
|
25
26
|
export type OpenOptions<Args> = {
|
|
26
27
|
timeout?: number;
|
|
28
|
+
existing?: ProgramMergeStrategy;
|
|
27
29
|
} & ProgramInitializationOptions<Args>;
|
|
28
30
|
export declare class Peerbit implements ProgramClient {
|
|
29
31
|
_libp2p: Libp2pExtended;
|
|
@@ -34,6 +36,7 @@ export declare class Peerbit implements ProgramClient {
|
|
|
34
36
|
private _libp2pExternal?;
|
|
35
37
|
private _identity;
|
|
36
38
|
private _keychain;
|
|
39
|
+
private _openQueue;
|
|
37
40
|
constructor(libp2p: Libp2pExtended, options: CreateOptions);
|
|
38
41
|
static create(options?: CreateInstanceOptions): Promise<Peerbit>;
|
|
39
42
|
get libp2p(): Libp2pExtended;
|
|
@@ -63,3 +66,4 @@ export declare class Peerbit implements ProgramClient {
|
|
|
63
66
|
open<S extends Program<Args>, Args = any>(storeOrAddress: S | Address | string, options?: OpenOptions<Args>): Promise<S>;
|
|
64
67
|
get memory(): LazyLevel;
|
|
65
68
|
}
|
|
69
|
+
export {};
|
package/lib/esm/peer.js
CHANGED
|
@@ -15,6 +15,7 @@ import { createLibp2pExtended, } from "./libp2p.js";
|
|
|
15
15
|
import { DirectBlock } from "@peerbit/blocks";
|
|
16
16
|
import { LevelDatastore } from "datastore-level";
|
|
17
17
|
import { BinaryWriter } from "@dao-xyz/borsh";
|
|
18
|
+
import PQueue from "p-queue";
|
|
18
19
|
export const logger = loggerFn({ module: "client" });
|
|
19
20
|
const isLibp2pInstance = (libp2p) => !!libp2p.getMultiaddrs;
|
|
20
21
|
const createLevel = (path) => {
|
|
@@ -43,6 +44,7 @@ export class Peerbit {
|
|
|
43
44
|
// Libp2p peerid in Identity form
|
|
44
45
|
_identity;
|
|
45
46
|
_keychain; // Keychain + Caching + X25519 keys
|
|
47
|
+
_openQueue;
|
|
46
48
|
constructor(libp2p, options) {
|
|
47
49
|
if (libp2p == null) {
|
|
48
50
|
throw new Error("Libp2p required");
|
|
@@ -62,6 +64,7 @@ export class Peerbit {
|
|
|
62
64
|
this.limitSigning = options.limitSigning || false;
|
|
63
65
|
this._cache = options.cache;
|
|
64
66
|
this._libp2pExternal = options.libp2pExternal;
|
|
67
|
+
this._openQueue = new PQueue({ concurrency: 1 });
|
|
65
68
|
}
|
|
66
69
|
static async create(options = {}) {
|
|
67
70
|
await sodium.ready; // Some of the modules depends on sodium to be readyy
|
|
@@ -189,7 +192,8 @@ export class Peerbit {
|
|
|
189
192
|
}
|
|
190
193
|
}
|
|
191
194
|
async stop() {
|
|
192
|
-
|
|
195
|
+
this._openQueue.clear();
|
|
196
|
+
await this._openQueue.onIdle();
|
|
193
197
|
// Close all open databases
|
|
194
198
|
await Promise.all([...this.programs.values()].map((program) => program.close()));
|
|
195
199
|
await this._cache.close();
|
|
@@ -204,16 +208,27 @@ export class Peerbit {
|
|
|
204
208
|
_onProgamClose(program) {
|
|
205
209
|
this.programs.delete(program.address.toString());
|
|
206
210
|
}
|
|
207
|
-
_onProgramOpen(program) {
|
|
211
|
+
async _onProgramOpen(program, mergeSrategy = "reject") {
|
|
208
212
|
const programAddress = program.address?.toString();
|
|
209
213
|
if (!programAddress) {
|
|
210
214
|
throw new Error("Missing program address");
|
|
211
215
|
}
|
|
212
216
|
if (this.programs.has(programAddress)) {
|
|
213
217
|
// second condition only makes this throw error if we are to add a new instance with the same address
|
|
214
|
-
|
|
218
|
+
if (mergeSrategy === "reject") {
|
|
219
|
+
throw new Error(`Program at ${programAddress} is already open`);
|
|
220
|
+
}
|
|
221
|
+
else if (mergeSrategy === "replace") {
|
|
222
|
+
const prev = this.programs.get(programAddress);
|
|
223
|
+
if (prev && prev !== program) {
|
|
224
|
+
await prev.close(); // clouse previous
|
|
225
|
+
}
|
|
226
|
+
this.programs.set(programAddress, program);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
this.programs.set(programAddress, program);
|
|
215
231
|
}
|
|
216
|
-
this.programs.set(programAddress, program);
|
|
217
232
|
}
|
|
218
233
|
/**
|
|
219
234
|
* Default behaviour of a store is only to accept heads that are forks (new roots) with some probability
|
|
@@ -223,61 +238,64 @@ export class Peerbit {
|
|
|
223
238
|
* @returns
|
|
224
239
|
*/
|
|
225
240
|
async open(storeOrAddress, options = {}) {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
241
|
+
const fn = async () => {
|
|
242
|
+
if (!this.libp2p.isStarted()) {
|
|
243
|
+
throw new Error("Can not open a store while disconnected");
|
|
244
|
+
}
|
|
245
|
+
// TODO add locks for store lifecycle, e.g. what happens if we try to open and close a store at the same time?
|
|
246
|
+
let program = storeOrAddress;
|
|
247
|
+
if (typeof storeOrAddress === "string") {
|
|
248
|
+
try {
|
|
249
|
+
if (this.programs?.has(storeOrAddress.toString())) {
|
|
250
|
+
throw new Error(`Program at ${storeOrAddress.toString()} is already open`);
|
|
251
|
+
}
|
|
252
|
+
else {
|
|
253
|
+
program = (await Program.load(storeOrAddress, this._libp2p.services.blocks, options)); // TODO fix typings
|
|
254
|
+
if (program instanceof Program === false) {
|
|
255
|
+
throw new Error(`Failed to open program because program is of type ${program?.constructor.name} and not ${Program.name}`);
|
|
256
|
+
}
|
|
240
257
|
}
|
|
241
258
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
throw error;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
else if (!program.closed) {
|
|
249
|
-
const existing = this.programs.get(program.address);
|
|
250
|
-
if (existing === program) {
|
|
251
|
-
return program;
|
|
252
|
-
}
|
|
253
|
-
else if (existing) {
|
|
254
|
-
throw new Error(`Program at ${program.address} is already open, but is another instance`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
logger.debug(`Open database '${program.constructor.name}`);
|
|
258
|
-
await program.beforeOpen(this, {
|
|
259
|
-
onOpen: (p) => {
|
|
260
|
-
if (p instanceof Program && p.parents.length === 1 && !p.parents[0]) {
|
|
261
|
-
return this._onProgramOpen(p);
|
|
259
|
+
catch (error) {
|
|
260
|
+
logger.error("Failed to load store with address: " + storeOrAddress.toString());
|
|
261
|
+
throw error;
|
|
262
262
|
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
263
|
+
}
|
|
264
|
+
else if (!program.closed) {
|
|
265
|
+
const existing = this.programs.get(program.address);
|
|
266
|
+
if (existing === program) {
|
|
267
|
+
return program;
|
|
267
268
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (p instanceof Program) {
|
|
271
|
-
return this._onProgamClose(p);
|
|
269
|
+
else if (existing) {
|
|
270
|
+
throw new Error(`Program at ${program.address} is already open, but is another instance`);
|
|
272
271
|
}
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
272
|
+
}
|
|
273
|
+
logger.debug(`Open database '${program.constructor.name}`);
|
|
274
|
+
await program.beforeOpen(this, {
|
|
275
|
+
onBeforeOpen: (p) => {
|
|
276
|
+
if (p instanceof Program && p.parents.length === 1 && !p.parents[0]) {
|
|
277
|
+
return this._onProgramOpen(p);
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
onClose: (p) => {
|
|
281
|
+
if (p instanceof Program) {
|
|
282
|
+
return this._onProgamClose(p);
|
|
283
|
+
}
|
|
284
|
+
},
|
|
285
|
+
onDrop: (p) => {
|
|
286
|
+
if (p instanceof Program) {
|
|
287
|
+
return this._onProgamClose(p);
|
|
288
|
+
}
|
|
289
|
+
},
|
|
290
|
+
...options,
|
|
291
|
+
// If the program opens more programs
|
|
292
|
+
// reset: options.reset,
|
|
293
|
+
});
|
|
294
|
+
await program.open(options.args);
|
|
295
|
+
await program.afterOpen();
|
|
296
|
+
return program;
|
|
297
|
+
};
|
|
298
|
+
return this._openQueue.add(fn); // TODO p-queue seem to return void type ;
|
|
281
299
|
}
|
|
282
300
|
get memory() {
|
|
283
301
|
return this._cache;
|
package/lib/esm/peer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"peer.js","sourceRoot":"","sources":["../../src/peer.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAa,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,cAAc,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,OAAO,GAIP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EACN,oBAAoB,GAGpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"peer.js","sourceRoot":"","sources":["../../src/peer.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,qBAAqB,CAAC;AAE5C,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAa,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE5E,OAAO,EACN,cAAc,EACd,gBAAgB,EAChB,cAAc,GACd,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACN,OAAO,GAIP,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,IAAI,MAAM,iBAAiB,CAAC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,iBAAiB,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAEvC,OAAO,EACN,oBAAoB,GAGpB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,MAAM,MAAM,SAAS,CAAC;AAE7B,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;AA4BrD,MAAM,gBAAgB,GAAG,CAAC,MAA4C,EAAE,EAAE,CACzE,CAAC,CAAE,MAAiB,CAAC,aAAa,CAAC;AAEpC,MAAM,WAAW,GAAG,CAAC,IAAa,EAA0C,EAAE;IAC7E,OAAO,IAAI;QACV,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC;QAC5C,CAAC,CAAC,IAAI,WAAW,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC;AAC/C,CAAC,CAAC;AAEF,MAAM,WAAW,GAAG,KAAK,EACxB,SAA6B,EAC7B,OAA6B,EAC5B,EAAE;IACH,MAAM,KAAK,GAAG,MAAM,IAAI,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;IAE1D,uCAAuC;IACvC,IAAI,KAAK;QAAE,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAI,OAAO,EAAE,KAAK,EAAE;QACnB,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC,KAAK,EAAE,CAAC;KAC9B;IAED,OAAO,KAAK,CAAC;AACd,CAAC,CAAC;AAEF,MAAM,OAAO,OAAO;IACnB,OAAO,CAAiB;IAExB,SAAS,CAAU;IAEnB,uCAAuC;IACvC,QAAQ,CAAuB;IAC/B,YAAY,CAAU;IAEd,MAAM,CAAY;IAClB,eAAe,GAAa,KAAK,CAAC;IAE1C,iCAAiC;IACzB,SAAS,CAAiB;IAE1B,SAAS,CAAiB,CAAC,mCAAmC;IAE9D,UAAU,CAAS;IAC3B,YAAY,MAAsB,EAAE,OAAsB;QACzD,IAAI,MAAM,IAAI,IAAI,EAAE;YACnB,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;SACnC;QACD,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;QACtB,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE;YAC1C,MAAM,IAAI,KAAK,CACd,iDAAiD;gBAChD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CACxB,CAAC;SACF;QAED,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE;YAC1C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;SACtD;QAED,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;QAElC,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACnC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;QAC1B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI,KAAK,CAAC;QAClD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;QAC9C,IAAI,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAiC,EAAE;QACtD,MAAM,MAAM,CAAC,KAAK,CAAC,CAAC,qDAAqD;QAEzE,IAAI,cAAc,GAAmB,OAAO,CAAC,MAAwB,CAAC;QACtE,MAAM,eAAe,GACpB,OAAO,CAAC,SAAS,IAAI,IAAI;YACxB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE;YACpD,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,cAAc,GAAG,KAAK,CAAC;QAE3B,MAAM,SAAS,GACd,OAAO,CAAC,SAAS,IAAI,IAAI;YACxB,CAAC,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;YACxE,CAAC,CAAC,SAAS,CAAC;QACd,IAAI,SAAS,EAAE;YACd,MAAM,SAAS,CAAC,IAAI,EAAE,CAAC;SACvB;QAED,IAAI,CAAC,cAAc,EAAE;YACpB,cAAc,GAAG,MAAM,oBAAoB,CAAC;gBAC3C,QAAQ,EAAE;oBACT,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;oBACjE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;iBAC/B;gBACD,kIAAkI;gBAClI,SAAS;aACT,CAAC,CAAC;SACH;aAAM;YACN,IAAI,gBAAgB,CAAC,cAAc,CAAC,EAAE;gBACrC,cAAc,GAAG,IAAI,CAAC,CAAC,6BAA6B;aACpD;iBAAM;gBACN,MAAM,eAAe,GAAG,cAA4C,CAAC;gBACrE,cAAc,GAAG,MAAM,oBAAoB,CAAC;oBAC3C,GAAG,eAAe;oBAClB,QAAQ,EAAE;wBACT,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,WAAW,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;wBACjE,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;wBAC/B,GAAG,eAAe,EAAE,QAAQ;qBAC5B;oBACD,SAAS;iBACT,CAAC,CAAC;aACH;SACD;QACD,IAAI,SAAS,EAAE;YACd,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,GAAG,KAAK,IAAI,EAAE;gBAChC,MAAM,MAAM,EAAE,CAAC;gBACf,MAAM,SAAS,EAAE,KAAK,EAAE,CAAC;YAC1B,CAAC,CAAC;SACF;QAED,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,EAAE;YAChC,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC;SAC7B;QAED,IAAI,cAAc,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE;YAC7C,MAAM,IAAI,KAAK,CACd,iDAAiD;gBAChD,cAAc,CAAC,MAAM,CAAC,IAAI,CAC3B,CAAC;SACF;QAED,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QACpC,MAAM,KAAK,GACV,OAAO,CAAC,KAAK;YACb,CAAC,MAAM,WAAW,CACjB,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CACtD,CAAC,CAAC;QAEJ,MAAM,QAAQ,GAAG,cAAc,CAAC,UAAU,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,cAAc,CAAC,cAAc,CAAC,QAAQ,EAAE;YAC5D,KAAK,EAAE,IAAI,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;SAC/B,CAAC,CAAC;QAEH,IAAI;YACH,MAAM,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC1B,MAAM,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;SACnD;QAAC,OAAO,KAAU,EAAE;YACpB,IAAI,KAAK,CAAC,IAAI,IAAI,wBAAwB,EAAE;gBAC3C,aAAa;aACb;iBAAM;gBACN,MAAM,KAAK,CAAC;aACZ;SACD;QAED,MAAM,IAAI,GAAG,IAAI,OAAO,CAAC,cAAc,EAAE;YACxC,SAAS;YACT,KAAK;YACL,cAAc;YACd,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,QAAQ;YACR,QAAQ;SACR,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IAED,IAAI,QAAQ;QACX,OAAO,IAAI,CAAC,SAAS,CAAC;IACvB,CAAC;IAED,aAAa;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IACpC,CAAC;IACD;;OAEG;IACH,KAAK,CAAC,IAAI,CACT,OAAyD;QAEzD,MAAM,QAAQ,GACb,OAAO,OAAO,IAAI,QAAQ;YACzB,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC;YACpB,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;gBAChD,CAAC,CAAC,OAAO;gBACT,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,SAAS,GAAG,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;QAErE,0FAA0F;QAC1F,OAAO,CACN,CAAC,MAAM,OAAO,CACb,GAAG,EAAE,CACJ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC3D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAC5D,CAAC,IAAI,KAAK,CACX,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACV,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE;YAC7B,IAAI,CAAC,eAAe,GAAG,KAAK,CAAC,CAAC,uDAAuD;YACrF,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;SAC3B;IACF,CAAC;IACD,KAAK,CAAC,IAAI;QACT,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;QAE/B,2BAA2B;QAC3B,MAAM,OAAO,CAAC,GAAG,CAChB,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,CAC7D,CAAC;QAEF,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QAE1B,6BAA6B;QAC7B,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE;YAC1B,iCAAiC;YACjC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SACzB;QAED,sCAAsC;QACtC,IAAI,CAAC,QAAQ,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3B,CAAC;IAEO,cAAc,CAAC,OAAgB;QACtC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,OAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAEO,KAAK,CAAC,cAAc,CAC3B,OAAgB,EAChB,eAAqC,QAAQ;QAE7C,MAAM,cAAc,GAAG,OAAO,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC;QACnD,IAAI,CAAC,cAAc,EAAE;YACpB,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;SAC3C;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE;YACtC,qGAAqG;YACrG,IAAI,YAAY,KAAK,QAAQ,EAAE;gBAC9B,MAAM,IAAI,KAAK,CAAC,cAAc,cAAc,kBAAkB,CAAC,CAAC;aAChE;iBAAM,IAAI,YAAY,KAAK,SAAS,EAAE;gBACtC,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC/C,IAAI,IAAI,IAAI,IAAI,KAAK,OAAO,EAAE;oBAC7B,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,kBAAkB;iBACtC;gBACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;aAC3C;SACD;aAAM;YACN,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;SAC3C;IACF,CAAC;IAED;;;;;;OAMG;IAEH,KAAK,CAAC,IAAI,CACT,cAAoC,EACpC,UAA6B,EAAE;QAE/B,MAAM,EAAE,GAAG,KAAK,IAAgB,EAAE;YACjC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE;gBAC7B,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;aAC3D;YAED,8GAA8G;YAE9G,IAAI,OAAO,GAAG,cAAmB,CAAC;YAClC,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE;gBACvC,IAAI;oBACH,IAAI,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,EAAE;wBAClD,MAAM,IAAI,KAAK,CACd,cAAc,cAAc,CAAC,QAAQ,EAAE,kBAAkB,CACzD,CAAC;qBACF;yBAAM;wBACN,OAAO,GAAG,CAAC,MAAM,OAAO,CAAC,IAAI,CAC5B,cAAc,EACd,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAC5B,OAAO,CACP,CAAM,CAAC,CAAC,mBAAmB;wBAC5B,IAAI,OAAO,YAAY,OAAO,KAAK,KAAK,EAAE;4BACzC,MAAM,IAAI,KAAK,CACd,qDAAqD,OAAO,EAAE,WAAW,CAAC,IAAI,YAAY,OAAO,CAAC,IAAI,EAAE,CACxG,CAAC;yBACF;qBACD;iBACD;gBAAC,OAAO,KAAK,EAAE;oBACf,MAAM,CAAC,KAAK,CACX,qCAAqC,GAAG,cAAc,CAAC,QAAQ,EAAE,CACjE,CAAC;oBACF,MAAM,KAAK,CAAC;iBACZ;aACD;iBAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE;gBAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;gBACpD,IAAI,QAAQ,KAAK,OAAO,EAAE;oBACzB,OAAO,OAAO,CAAC;iBACf;qBAAM,IAAI,QAAQ,EAAE;oBACpB,MAAM,IAAI,KAAK,CACd,cAAc,OAAO,CAAC,OAAO,2CAA2C,CACxE,CAAC;iBACF;aACD;YAED,MAAM,CAAC,KAAK,CAAC,kBAAkB,OAAO,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;YAC3D,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE;gBAC9B,YAAY,EAAE,CAAC,CAAC,EAAE,EAAE;oBACnB,IAAI,CAAC,YAAY,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;wBACpE,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;qBAC9B;gBACF,CAAC;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,IAAI,CAAC,YAAY,OAAO,EAAE;wBACzB,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;qBAC9B;gBACF,CAAC;gBACD,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;oBACb,IAAI,CAAC,YAAY,OAAO,EAAE;wBACzB,OAAO,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;qBAC9B;gBACF,CAAC;gBACD,GAAG,OAAO;gBACV,qCAAqC;gBACrC,wBAAwB;aACxB,CAAC,CAAC;YAEH,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YACjC,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC;YAE1B,OAAO,OAAY,CAAC;QACrB,CAAC,CAAC;QACF,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAa,CAAC,CAAC,0CAA0C;IACvF,CAAC;IAED,IAAI,MAAM;QACT,OAAO,IAAI,CAAC,MAAM,CAAC;IACpB,CAAC;CACD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "peerbit",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Peerbit client",
|
|
5
5
|
"author": "dao.xyz",
|
|
6
6
|
"license": "MIT",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@peerbit/crypto": "1.0.2",
|
|
45
45
|
"@peerbit/lazy-level": "1.0.0",
|
|
46
46
|
"@peerbit/logger": "1.0.0",
|
|
47
|
-
"@peerbit/program": "1.0.
|
|
47
|
+
"@peerbit/program": "1.0.4",
|
|
48
48
|
"@peerbit/pubsub": "^1.0.4",
|
|
49
49
|
"@peerbit/uint8arrays": "3.0.0",
|
|
50
50
|
"datastore-level": "^10.1.2",
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"p2p",
|
|
75
75
|
"peer-to-peer"
|
|
76
76
|
],
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "f4c3f07242fa4ee586748d106e64664e3b58e97a"
|
|
78
78
|
}
|
package/src/peer.ts
CHANGED
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
import { DirectBlock } from "@peerbit/blocks";
|
|
32
32
|
import { LevelDatastore } from "datastore-level";
|
|
33
33
|
import { BinaryWriter } from "@dao-xyz/borsh";
|
|
34
|
+
import PQueue from "p-queue";
|
|
34
35
|
|
|
35
36
|
export const logger = loggerFn({ module: "client" });
|
|
36
37
|
|
|
@@ -52,8 +53,10 @@ export type CreateInstanceOptions = {
|
|
|
52
53
|
directory?: string;
|
|
53
54
|
cache?: LazyLevel;
|
|
54
55
|
} & OptionalCreateOptions;
|
|
56
|
+
type ProgramMergeStrategy = "replace" | "reject";
|
|
55
57
|
export type OpenOptions<Args> = {
|
|
56
58
|
timeout?: number;
|
|
59
|
+
existing?: ProgramMergeStrategy;
|
|
57
60
|
/*
|
|
58
61
|
reset?: boolean; */
|
|
59
62
|
} & ProgramInitializationOptions<Args>;
|
|
@@ -99,6 +102,7 @@ export class Peerbit implements ProgramClient {
|
|
|
99
102
|
|
|
100
103
|
private _keychain: Libp2pKeychain; // Keychain + Caching + X25519 keys
|
|
101
104
|
|
|
105
|
+
private _openQueue: PQueue;
|
|
102
106
|
constructor(libp2p: Libp2pExtended, options: CreateOptions) {
|
|
103
107
|
if (libp2p == null) {
|
|
104
108
|
throw new Error("Libp2p required");
|
|
@@ -123,6 +127,7 @@ export class Peerbit implements ProgramClient {
|
|
|
123
127
|
this.limitSigning = options.limitSigning || false;
|
|
124
128
|
this._cache = options.cache;
|
|
125
129
|
this._libp2pExternal = options.libp2pExternal;
|
|
130
|
+
this._openQueue = new PQueue({ concurrency: 1 });
|
|
126
131
|
}
|
|
127
132
|
|
|
128
133
|
static async create(options: CreateInstanceOptions = {}): Promise<Peerbit> {
|
|
@@ -278,7 +283,8 @@ export class Peerbit implements ProgramClient {
|
|
|
278
283
|
}
|
|
279
284
|
}
|
|
280
285
|
async stop() {
|
|
281
|
-
|
|
286
|
+
this._openQueue.clear();
|
|
287
|
+
await this._openQueue.onIdle();
|
|
282
288
|
|
|
283
289
|
// Close all open databases
|
|
284
290
|
await Promise.all(
|
|
@@ -301,17 +307,28 @@ export class Peerbit implements ProgramClient {
|
|
|
301
307
|
this.programs.delete(program.address!.toString());
|
|
302
308
|
}
|
|
303
309
|
|
|
304
|
-
private _onProgramOpen(
|
|
310
|
+
private async _onProgramOpen(
|
|
311
|
+
program: Program,
|
|
312
|
+
mergeSrategy: ProgramMergeStrategy = "reject"
|
|
313
|
+
) {
|
|
305
314
|
const programAddress = program.address?.toString();
|
|
306
315
|
if (!programAddress) {
|
|
307
316
|
throw new Error("Missing program address");
|
|
308
317
|
}
|
|
309
318
|
if (this.programs.has(programAddress)) {
|
|
310
319
|
// second condition only makes this throw error if we are to add a new instance with the same address
|
|
311
|
-
|
|
320
|
+
if (mergeSrategy === "reject") {
|
|
321
|
+
throw new Error(`Program at ${programAddress} is already open`);
|
|
322
|
+
} else if (mergeSrategy === "replace") {
|
|
323
|
+
const prev = this.programs.get(programAddress);
|
|
324
|
+
if (prev && prev !== program) {
|
|
325
|
+
await prev.close(); // clouse previous
|
|
326
|
+
}
|
|
327
|
+
this.programs.set(programAddress, program);
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
this.programs.set(programAddress, program);
|
|
312
331
|
}
|
|
313
|
-
|
|
314
|
-
this.programs.set(programAddress, program);
|
|
315
332
|
}
|
|
316
333
|
|
|
317
334
|
/**
|
|
@@ -326,74 +343,77 @@ export class Peerbit implements ProgramClient {
|
|
|
326
343
|
storeOrAddress: S | Address | string,
|
|
327
344
|
options: OpenOptions<Args> = {}
|
|
328
345
|
): Promise<S> {
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
346
|
+
const fn = async (): Promise<S> => {
|
|
347
|
+
if (!this.libp2p.isStarted()) {
|
|
348
|
+
throw new Error("Can not open a store while disconnected");
|
|
349
|
+
}
|
|
332
350
|
|
|
333
|
-
|
|
351
|
+
// TODO add locks for store lifecycle, e.g. what happens if we try to open and close a store at the same time?
|
|
334
352
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
throw new Error(
|
|
340
|
-
`Program at ${storeOrAddress.toString()} is already open`
|
|
341
|
-
);
|
|
342
|
-
} else {
|
|
343
|
-
program = (await Program.load(
|
|
344
|
-
storeOrAddress,
|
|
345
|
-
this._libp2p.services.blocks,
|
|
346
|
-
options
|
|
347
|
-
)) as S; // TODO fix typings
|
|
348
|
-
if (program instanceof Program === false) {
|
|
353
|
+
let program = storeOrAddress as S;
|
|
354
|
+
if (typeof storeOrAddress === "string") {
|
|
355
|
+
try {
|
|
356
|
+
if (this.programs?.has(storeOrAddress.toString())) {
|
|
349
357
|
throw new Error(
|
|
350
|
-
`
|
|
358
|
+
`Program at ${storeOrAddress.toString()} is already open`
|
|
351
359
|
);
|
|
360
|
+
} else {
|
|
361
|
+
program = (await Program.load(
|
|
362
|
+
storeOrAddress,
|
|
363
|
+
this._libp2p.services.blocks,
|
|
364
|
+
options
|
|
365
|
+
)) as S; // TODO fix typings
|
|
366
|
+
if (program instanceof Program === false) {
|
|
367
|
+
throw new Error(
|
|
368
|
+
`Failed to open program because program is of type ${program?.constructor.name} and not ${Program.name}`
|
|
369
|
+
);
|
|
370
|
+
}
|
|
352
371
|
}
|
|
372
|
+
} catch (error) {
|
|
373
|
+
logger.error(
|
|
374
|
+
"Failed to load store with address: " + storeOrAddress.toString()
|
|
375
|
+
);
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
378
|
+
} else if (!program.closed) {
|
|
379
|
+
const existing = this.programs.get(program.address);
|
|
380
|
+
if (existing === program) {
|
|
381
|
+
return program;
|
|
382
|
+
} else if (existing) {
|
|
383
|
+
throw new Error(
|
|
384
|
+
`Program at ${program.address} is already open, but is another instance`
|
|
385
|
+
);
|
|
353
386
|
}
|
|
354
|
-
} catch (error) {
|
|
355
|
-
logger.error(
|
|
356
|
-
"Failed to load store with address: " + storeOrAddress.toString()
|
|
357
|
-
);
|
|
358
|
-
throw error;
|
|
359
|
-
}
|
|
360
|
-
} else if (!program.closed) {
|
|
361
|
-
const existing = this.programs.get(program.address);
|
|
362
|
-
if (existing === program) {
|
|
363
|
-
return program;
|
|
364
|
-
} else if (existing) {
|
|
365
|
-
throw new Error(
|
|
366
|
-
`Program at ${program.address} is already open, but is another instance`
|
|
367
|
-
);
|
|
368
387
|
}
|
|
369
|
-
}
|
|
370
388
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
389
|
+
logger.debug(`Open database '${program.constructor.name}`);
|
|
390
|
+
await program.beforeOpen(this, {
|
|
391
|
+
onBeforeOpen: (p) => {
|
|
392
|
+
if (p instanceof Program && p.parents.length === 1 && !p.parents[0]) {
|
|
393
|
+
return this._onProgramOpen(p);
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
onClose: (p) => {
|
|
397
|
+
if (p instanceof Program) {
|
|
398
|
+
return this._onProgamClose(p);
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
onDrop: (p) => {
|
|
402
|
+
if (p instanceof Program) {
|
|
403
|
+
return this._onProgamClose(p);
|
|
404
|
+
}
|
|
405
|
+
},
|
|
406
|
+
...options,
|
|
407
|
+
// If the program opens more programs
|
|
408
|
+
// reset: options.reset,
|
|
409
|
+
});
|
|
392
410
|
|
|
393
|
-
|
|
394
|
-
|
|
411
|
+
await program.open(options.args);
|
|
412
|
+
await program.afterOpen();
|
|
395
413
|
|
|
396
|
-
|
|
414
|
+
return program as S;
|
|
415
|
+
};
|
|
416
|
+
return this._openQueue.add(fn) as any as S; // TODO p-queue seem to return void type ;
|
|
397
417
|
}
|
|
398
418
|
|
|
399
419
|
get memory() {
|