@peerbit/blocks 1.1.7 → 2.0.2
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/{level.d.ts → any-blockstore.d.ts} +7 -11
- package/lib/esm/{level.js → any-blockstore.js} +21 -30
- package/lib/esm/any-blockstore.js.map +1 -0
- package/lib/esm/block.d.ts +2 -2
- package/lib/esm/block.js.map +1 -1
- package/lib/esm/index.d.ts +3 -2
- package/lib/esm/index.js +3 -2
- package/lib/esm/index.js.map +1 -1
- package/lib/esm/{store.d.ts → interface.d.ts} +2 -1
- package/lib/esm/interface.js +2 -0
- package/lib/esm/interface.js.map +1 -0
- package/lib/esm/libp2p.d.ts +5 -20
- package/lib/esm/libp2p.js +38 -177
- package/lib/esm/libp2p.js.map +1 -1
- package/lib/esm/remote.d.ts +59 -0
- package/lib/esm/remote.js +245 -0
- package/lib/esm/remote.js.map +1 -0
- package/package.json +8 -10
- package/src/{level.ts → any-blockstore.ts} +25 -37
- package/src/block.ts +1 -1
- package/src/index.ts +3 -2
- package/src/{store.ts → interface.ts} +4 -1
- package/src/libp2p.ts +45 -195
- package/src/remote.ts +298 -0
- package/lib/esm/level.js.map +0 -1
- package/lib/esm/store.js +0 -2
- package/lib/esm/store.js.map +0 -1
- package/lib/esm/streams.d.ts +0 -1
- package/lib/esm/streams.js +0 -2
- package/lib/esm/streams.js.map +0 -1
- package/src/streams.ts +0 -1
package/src/libp2p.ts
CHANGED
|
@@ -1,63 +1,21 @@
|
|
|
1
|
-
import { BlockStore } from "./
|
|
1
|
+
import { BlockStore } from "./interface.js";
|
|
2
2
|
import { Blocks as IBlocks } from "@peerbit/blocks-interface";
|
|
3
|
-
import {
|
|
4
|
-
stringifyCid,
|
|
5
|
-
cidifyString,
|
|
6
|
-
codecCodes,
|
|
7
|
-
checkDecodeBlock
|
|
8
|
-
} from "./block.js";
|
|
9
|
-
import { variant, field, serialize, deserialize } from "@dao-xyz/borsh";
|
|
10
|
-
import { CID } from "multiformats/cid";
|
|
11
|
-
import { DataMessage } from "@peerbit/stream-interface";
|
|
12
3
|
import { DirectStream } from "@peerbit/stream";
|
|
13
|
-
|
|
14
|
-
import * as Block from "multiformats/block";
|
|
15
|
-
import { PublicSignKey } from "@peerbit/crypto";
|
|
16
4
|
import { DirectStreamComponents } from "@peerbit/stream";
|
|
17
|
-
import {
|
|
18
|
-
import { Level } from "level";
|
|
5
|
+
import { AnyBlockStore } from "./any-blockstore.js";
|
|
19
6
|
import { GetOptions } from "@peerbit/blocks-interface";
|
|
20
|
-
import
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@
|
|
25
|
-
export class BlockRequest extends BlockMessage {
|
|
26
|
-
@field({ type: "string" })
|
|
27
|
-
cid: string;
|
|
28
|
-
|
|
29
|
-
constructor(cid: string) {
|
|
30
|
-
super();
|
|
31
|
-
this.cid = cid;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
@variant(1)
|
|
36
|
-
export class BlockResponse extends BlockMessage {
|
|
37
|
-
@field({ type: "string" })
|
|
38
|
-
cid: string;
|
|
39
|
-
|
|
40
|
-
@field({ type: Uint8Array })
|
|
41
|
-
bytes: Uint8Array;
|
|
42
|
-
|
|
43
|
-
constructor(cid: string, bytes: Uint8Array) {
|
|
44
|
-
super();
|
|
45
|
-
this.cid = cid;
|
|
46
|
-
this.bytes = bytes;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
7
|
+
import { createStore } from "@peerbit/any-store";
|
|
8
|
+
import { BlockMessage, RemoteBlocks } from "./remote.js";
|
|
9
|
+
import { PublicSignKey } from "@peerbit/crypto";
|
|
10
|
+
import { DataMessage } from "@peerbit/stream-interface";
|
|
11
|
+
import { deserialize, serialize } from "@dao-xyz/borsh";
|
|
49
12
|
|
|
50
13
|
export type DirectBlockComponents = DirectStreamComponents;
|
|
14
|
+
|
|
51
15
|
export class DirectBlock extends DirectStream implements IBlocks {
|
|
52
|
-
private
|
|
53
|
-
private
|
|
54
|
-
private
|
|
55
|
-
private _loadFetchQueue: PQueue;
|
|
56
|
-
private _readFromPeersPromises: Map<
|
|
57
|
-
string,
|
|
58
|
-
Promise<Block.Block<any, any, any, 1> | undefined> | undefined
|
|
59
|
-
>;
|
|
60
|
-
_open = false;
|
|
16
|
+
private remoteBlocks: RemoteBlocks;
|
|
17
|
+
private onDataFn: any;
|
|
18
|
+
private onPeerConnectedFn: any;
|
|
61
19
|
|
|
62
20
|
constructor(
|
|
63
21
|
components: DirectBlockComponents,
|
|
@@ -68,183 +26,75 @@ export class DirectBlock extends DirectStream implements IBlocks {
|
|
|
68
26
|
messageProcessingConcurrency?: number;
|
|
69
27
|
}
|
|
70
28
|
) {
|
|
71
|
-
super(components, ["
|
|
72
|
-
emitSelf: false,
|
|
29
|
+
super(components, ["/lazyblock/0.0.0"], {
|
|
73
30
|
signaturePolicy: "StrictNoSign",
|
|
74
31
|
messageProcessingConcurrency: options?.messageProcessingConcurrency || 10,
|
|
75
|
-
canRelayMessage: options?.canRelayMessage ?? true
|
|
32
|
+
canRelayMessage: options?.canRelayMessage ?? true,
|
|
33
|
+
connectionManager: {
|
|
34
|
+
dialer: false,
|
|
35
|
+
pruner: false
|
|
36
|
+
}
|
|
76
37
|
});
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
38
|
+
this.remoteBlocks = new RemoteBlocks({
|
|
39
|
+
local: new AnyBlockStore(createStore(options?.directory)),
|
|
40
|
+
publish: (message) => this.publish(serialize(message)),
|
|
41
|
+
localTimeout: options?.localTimeout || 1000,
|
|
42
|
+
messageProcessingConcurrency: options?.messageProcessingConcurrency || 10,
|
|
43
|
+
waitFor: this.waitFor.bind(this)
|
|
81
44
|
});
|
|
82
|
-
this._localStore =
|
|
83
|
-
options?.directory != null
|
|
84
|
-
? new LevelBlockStore(new Level(options.directory))
|
|
85
|
-
: new MemoryLevelBlockStore();
|
|
86
|
-
this._resolvers = new Map();
|
|
87
|
-
this._readFromPeersPromises = new Map();
|
|
88
|
-
this._responseHandler = async (evt: CustomEvent<DataMessage>) => {
|
|
89
|
-
if (!evt) {
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
const message = evt.detail;
|
|
93
|
-
try {
|
|
94
|
-
const decoded = deserialize(message.data, BlockMessage);
|
|
95
|
-
if (decoded instanceof BlockRequest && this._localStore) {
|
|
96
|
-
this._loadFetchQueue.add(() =>
|
|
97
|
-
this.handleFetchRequest(decoded, localTimeout)
|
|
98
|
-
);
|
|
99
|
-
} else if (decoded instanceof BlockResponse) {
|
|
100
|
-
// TODO make sure we are not storing too much bytes in ram (like filter large blocks)
|
|
101
45
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
46
|
+
this.onDataFn = (data: CustomEvent<DataMessage>) => {
|
|
47
|
+
data.detail?.data &&
|
|
48
|
+
this.remoteBlocks.onMessage(
|
|
49
|
+
deserialize(data.detail.data!, BlockMessage)
|
|
50
|
+
);
|
|
108
51
|
};
|
|
52
|
+
this.onPeerConnectedFn = (evt: CustomEvent<PublicSignKey>) =>
|
|
53
|
+
this.remoteBlocks.onReachable(evt.detail);
|
|
109
54
|
}
|
|
110
55
|
|
|
111
56
|
async put(bytes: Uint8Array): Promise<string> {
|
|
112
|
-
|
|
113
|
-
throw new Error("Local store not set");
|
|
114
|
-
}
|
|
115
|
-
return this._localStore!.put(bytes);
|
|
57
|
+
return this.remoteBlocks.put(bytes);
|
|
116
58
|
}
|
|
117
59
|
|
|
118
60
|
async has(cid: string) {
|
|
119
|
-
return this.
|
|
61
|
+
return this.remoteBlocks.has(cid);
|
|
120
62
|
}
|
|
121
63
|
async get(
|
|
122
64
|
cid: string,
|
|
123
65
|
options?: GetOptions | undefined
|
|
124
66
|
): Promise<Uint8Array | undefined> {
|
|
125
|
-
|
|
126
|
-
let value = this._localStore
|
|
127
|
-
? await this._localStore.get(cid, options)
|
|
128
|
-
: undefined;
|
|
129
|
-
|
|
130
|
-
if (!value) {
|
|
131
|
-
// try to get it remotelly
|
|
132
|
-
value = await this._readFromPeers(cid, cidObject, options);
|
|
133
|
-
if (options?.replicate && value) {
|
|
134
|
-
this._localStore!.put(value);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
return value;
|
|
67
|
+
return this.remoteBlocks.get(cid, options);
|
|
138
68
|
}
|
|
139
69
|
|
|
140
70
|
async rm(cid: string) {
|
|
141
|
-
|
|
71
|
+
return this.remoteBlocks.rm(cid);
|
|
142
72
|
}
|
|
143
73
|
|
|
144
74
|
async *iterator(): AsyncGenerator<[string, Uint8Array], void, void> {
|
|
145
|
-
for await (const [key, value] of this.
|
|
75
|
+
for await (const [key, value] of this.remoteBlocks.iterator()) {
|
|
146
76
|
yield [key, value];
|
|
147
77
|
}
|
|
148
78
|
}
|
|
149
79
|
|
|
150
80
|
async start(): Promise<void> {
|
|
151
|
-
|
|
81
|
+
this.addEventListener("data", this.onDataFn);
|
|
82
|
+
this.addEventListener("peer:reachable", this.onPeerConnectedFn);
|
|
152
83
|
await super.start();
|
|
153
|
-
this.
|
|
154
|
-
this._open = true;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private async handleFetchRequest(
|
|
158
|
-
request: BlockRequest,
|
|
159
|
-
localTimeout: number
|
|
160
|
-
) {
|
|
161
|
-
const cid = stringifyCid(request.cid);
|
|
162
|
-
const bytes = await this._localStore.get(cid, {
|
|
163
|
-
timeout: localTimeout
|
|
164
|
-
});
|
|
165
|
-
if (!bytes) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
const response = serialize(new BlockResponse(cid, bytes));
|
|
169
|
-
await this.publish(response);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
private async _readFromPeers(
|
|
173
|
-
cidString: string,
|
|
174
|
-
cidObject: CID,
|
|
175
|
-
options: { timeout?: number; hasher?: any } = {}
|
|
176
|
-
): Promise<Uint8Array | undefined> {
|
|
177
|
-
const codec = codecCodes[cidObject.code];
|
|
178
|
-
let promise = this._readFromPeersPromises.get(cidString);
|
|
179
|
-
if (!promise) {
|
|
180
|
-
promise = new Promise<Block.Block<any, any, any, 1> | undefined>(
|
|
181
|
-
(resolve, reject) => {
|
|
182
|
-
const timeoutCallback = setTimeout(
|
|
183
|
-
() => {
|
|
184
|
-
resolve(undefined);
|
|
185
|
-
},
|
|
186
|
-
options.timeout || 30 * 1000
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
this._resolvers.set(cidString, async (bytes: Uint8Array) => {
|
|
190
|
-
const value = await checkDecodeBlock(cidObject, bytes, {
|
|
191
|
-
codec,
|
|
192
|
-
hasher: options?.hasher
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
clearTimeout(timeoutCallback);
|
|
196
|
-
this._resolvers.delete(cidString); // TODO concurrency might not work as expected here
|
|
197
|
-
resolve(value);
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
);
|
|
201
|
-
|
|
202
|
-
this._readFromPeersPromises.set(cidString, promise);
|
|
203
|
-
|
|
204
|
-
const publish = (to?: PublicSignKey[]) =>
|
|
205
|
-
this.publish(serialize(new BlockRequest(cidString)), { to: to });
|
|
206
|
-
|
|
207
|
-
const publishOnNewPeers = (e: CustomEvent<PublicSignKey>) => {
|
|
208
|
-
return publish([e.detail]);
|
|
209
|
-
};
|
|
210
|
-
this.addEventListener("peer:reachable", publishOnNewPeers);
|
|
211
|
-
await publish();
|
|
212
|
-
|
|
213
|
-
// we want to make sure that if some new peers join, we also try to ask them
|
|
214
|
-
|
|
215
|
-
const result = await promise;
|
|
216
|
-
this._readFromPeersPromises.delete(cidString);
|
|
217
|
-
|
|
218
|
-
// stop asking new peers, because we already got an response
|
|
219
|
-
this.removeEventListener("peer:reachable", publishOnNewPeers);
|
|
220
|
-
return result?.bytes;
|
|
221
|
-
} else {
|
|
222
|
-
const result = await promise;
|
|
223
|
-
return result?.bytes;
|
|
224
|
-
}
|
|
84
|
+
await this.remoteBlocks.start();
|
|
225
85
|
}
|
|
226
86
|
|
|
227
87
|
async stop(): Promise<void> {
|
|
228
|
-
|
|
229
|
-
this.removeEventListener("
|
|
230
|
-
|
|
231
|
-
// Wait for processing request
|
|
232
|
-
this._loadFetchQueue.clear();
|
|
233
|
-
await this._loadFetchQueue.onIdle(); // wait for pending
|
|
88
|
+
this.removeEventListener("data", this.onDataFn);
|
|
89
|
+
this.removeEventListener("peer:reachable", this.onPeerConnectedFn);
|
|
234
90
|
await super.stop();
|
|
235
|
-
await this.
|
|
236
|
-
this._readFromPeersPromises.clear();
|
|
237
|
-
this._resolvers.clear();
|
|
238
|
-
this._open = false;
|
|
239
|
-
|
|
240
|
-
// we dont cleanup subscription because we dont know if someone else is sbuscribing also
|
|
91
|
+
await this.remoteBlocks.stop();
|
|
241
92
|
}
|
|
242
93
|
|
|
94
|
+
async size() {
|
|
95
|
+
return this.remoteBlocks?.size() || 0;
|
|
96
|
+
}
|
|
243
97
|
get status() {
|
|
244
|
-
|
|
245
|
-
return this._localStore?.status() || this.started;
|
|
246
|
-
} else {
|
|
247
|
-
return "closed";
|
|
248
|
-
}
|
|
98
|
+
return this.remoteBlocks?.status || this.started;
|
|
249
99
|
}
|
|
250
100
|
}
|
package/src/remote.ts
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { BlockStore } from "./interface.js";
|
|
2
|
+
import { Blocks as IBlocks } from "@peerbit/blocks-interface";
|
|
3
|
+
import {
|
|
4
|
+
stringifyCid,
|
|
5
|
+
cidifyString,
|
|
6
|
+
codecCodes,
|
|
7
|
+
checkDecodeBlock
|
|
8
|
+
} from "./block.js";
|
|
9
|
+
import { variant, field, serialize, deserialize } from "@dao-xyz/borsh";
|
|
10
|
+
import { CID } from "multiformats/cid";
|
|
11
|
+
import * as Block from "multiformats/block";
|
|
12
|
+
import { PublicSignKey } from "@peerbit/crypto";
|
|
13
|
+
import { AnyBlockStore } from "./any-blockstore.js";
|
|
14
|
+
import { GetOptions } from "@peerbit/blocks-interface";
|
|
15
|
+
import PQueue from "p-queue";
|
|
16
|
+
import { AbortError } from "@peerbit/time";
|
|
17
|
+
import type { PeerId } from "@libp2p/interface/peer-id";
|
|
18
|
+
import { TypedEventEmitter, CustomEvent } from "@libp2p/interface";
|
|
19
|
+
|
|
20
|
+
export class BlockMessage {}
|
|
21
|
+
|
|
22
|
+
@variant(0)
|
|
23
|
+
export class BlockRequest extends BlockMessage {
|
|
24
|
+
@field({ type: "string" })
|
|
25
|
+
cid: string;
|
|
26
|
+
|
|
27
|
+
constructor(cid: string) {
|
|
28
|
+
super();
|
|
29
|
+
this.cid = cid;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@variant(1)
|
|
34
|
+
export class BlockResponse extends BlockMessage {
|
|
35
|
+
@field({ type: "string" })
|
|
36
|
+
cid: string;
|
|
37
|
+
|
|
38
|
+
@field({ type: Uint8Array })
|
|
39
|
+
bytes: Uint8Array;
|
|
40
|
+
|
|
41
|
+
constructor(cid: string, bytes: Uint8Array) {
|
|
42
|
+
super();
|
|
43
|
+
this.cid = cid;
|
|
44
|
+
this.bytes = bytes;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class RemoteBlocks implements IBlocks {
|
|
49
|
+
localStore: BlockStore;
|
|
50
|
+
|
|
51
|
+
private _responseHandler?: (data: BlockMessage) => any;
|
|
52
|
+
private _resolvers: Map<string, (data: Uint8Array) => void>;
|
|
53
|
+
private _loadFetchQueue: PQueue;
|
|
54
|
+
private _readFromPeersPromises: Map<
|
|
55
|
+
string,
|
|
56
|
+
Promise<Block.Block<any, any, any, 1> | undefined> | undefined
|
|
57
|
+
>;
|
|
58
|
+
_open = false;
|
|
59
|
+
private _events: TypedEventEmitter<{
|
|
60
|
+
"peer:reachable": CustomEvent<PublicSignKey>;
|
|
61
|
+
}>;
|
|
62
|
+
private closeController: AbortController;
|
|
63
|
+
|
|
64
|
+
constructor(
|
|
65
|
+
readonly options: {
|
|
66
|
+
local: AnyBlockStore;
|
|
67
|
+
localTimeout?: number;
|
|
68
|
+
messageProcessingConcurrency?: number;
|
|
69
|
+
publish: (
|
|
70
|
+
message: BlockRequest | BlockResponse,
|
|
71
|
+
options?: { to?: string[] }
|
|
72
|
+
) => Promise<Uint8Array | void>;
|
|
73
|
+
waitFor(peer: PeerId | PublicSignKey): Promise<void>;
|
|
74
|
+
}
|
|
75
|
+
) {
|
|
76
|
+
const localTimeout = options?.localTimeout || 1000;
|
|
77
|
+
this._loadFetchQueue = new PQueue({
|
|
78
|
+
concurrency: options?.messageProcessingConcurrency || 10
|
|
79
|
+
});
|
|
80
|
+
this.localStore = options?.local;
|
|
81
|
+
this._resolvers = new Map();
|
|
82
|
+
this._readFromPeersPromises = new Map();
|
|
83
|
+
/* this._responseHandler = (async (evt: CustomEvent<DataMessage>) => {
|
|
84
|
+
if (!evt) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const message = evt.detail;
|
|
88
|
+
if (!message.data) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
try {
|
|
93
|
+
const decoded = deserialize(message.data, BlockMessage);
|
|
94
|
+
if (decoded instanceof BlockRequest && this._localStore) {
|
|
95
|
+
this._loadFetchQueue.add(() =>
|
|
96
|
+
this.handleFetchRequest(decoded, localTimeout)
|
|
97
|
+
);
|
|
98
|
+
} else if (decoded instanceof BlockResponse) {
|
|
99
|
+
// TODO make sure we are not storing too much bytes in ram (like filter large blocks)
|
|
100
|
+
|
|
101
|
+
this._resolvers.get(decoded.cid)?.(decoded.bytes);
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.error("Got error for libp2p block transport: ", error);
|
|
105
|
+
return; // timeout o r invalid cid
|
|
106
|
+
}
|
|
107
|
+
}) */
|
|
108
|
+
|
|
109
|
+
this._responseHandler = async (message: BlockMessage) => {
|
|
110
|
+
try {
|
|
111
|
+
if (message instanceof BlockRequest && this.localStore) {
|
|
112
|
+
this._loadFetchQueue.add(() =>
|
|
113
|
+
this.handleFetchRequest(message, localTimeout)
|
|
114
|
+
);
|
|
115
|
+
} else if (message instanceof BlockResponse) {
|
|
116
|
+
// TODO make sure we are not storing too much bytes in ram (like filter large blocks)
|
|
117
|
+
|
|
118
|
+
this._resolvers.get(message.cid)?.(message.bytes);
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
console.error("Got error for libp2p block transport: ", error);
|
|
122
|
+
return; // timeout o r invalid cid
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
async put(bytes: Uint8Array): Promise<string> {
|
|
128
|
+
if (!this.localStore) {
|
|
129
|
+
throw new Error("Local store not set");
|
|
130
|
+
}
|
|
131
|
+
return this.localStore!.put(bytes);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async has(cid: string) {
|
|
135
|
+
return this.localStore.has(cid);
|
|
136
|
+
}
|
|
137
|
+
async get(
|
|
138
|
+
cid: string,
|
|
139
|
+
options?: GetOptions | undefined
|
|
140
|
+
): Promise<Uint8Array | undefined> {
|
|
141
|
+
const cidObject = cidifyString(cid);
|
|
142
|
+
let value = this.localStore
|
|
143
|
+
? await this.localStore.get(cid, options)
|
|
144
|
+
: undefined;
|
|
145
|
+
|
|
146
|
+
if (!value) {
|
|
147
|
+
// try to get it remotelly
|
|
148
|
+
value = await this._readFromPeers(cid, cidObject, options);
|
|
149
|
+
if (options?.replicate && value) {
|
|
150
|
+
this.localStore!.put(value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return value;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async rm(cid: string) {
|
|
157
|
+
await this.localStore?.rm(cid);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async *iterator(): AsyncGenerator<[string, Uint8Array], void, void> {
|
|
161
|
+
for await (const [key, value] of this.localStore.iterator()) {
|
|
162
|
+
yield [key, value];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
async start(): Promise<void> {
|
|
167
|
+
this._events = new TypedEventEmitter();
|
|
168
|
+
this.closeController = new AbortController();
|
|
169
|
+
await this.localStore?.start();
|
|
170
|
+
this._open = true;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
onMessage(data: BlockMessage) {
|
|
174
|
+
return this._responseHandler!(data);
|
|
175
|
+
}
|
|
176
|
+
onReachable(publicKey: PublicSignKey) {
|
|
177
|
+
this._events.dispatchEvent(
|
|
178
|
+
new CustomEvent("peer:reachable", { detail: publicKey })
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
private async handleFetchRequest(
|
|
183
|
+
request: BlockRequest,
|
|
184
|
+
localTimeout: number
|
|
185
|
+
) {
|
|
186
|
+
const cid = stringifyCid(request.cid);
|
|
187
|
+
const bytes = await this.localStore.get(cid, {
|
|
188
|
+
timeout: localTimeout
|
|
189
|
+
});
|
|
190
|
+
if (!bytes) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
await this.options.publish(new BlockResponse(cid, bytes));
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private async _readFromPeers(
|
|
197
|
+
cidString: string,
|
|
198
|
+
cidObject: CID,
|
|
199
|
+
options: { timeout?: number; hasher?: any; from?: string[] } = {}
|
|
200
|
+
): Promise<Uint8Array | undefined> {
|
|
201
|
+
const codec = codecCodes[cidObject.code];
|
|
202
|
+
let promise = this._readFromPeersPromises.get(cidString);
|
|
203
|
+
if (!promise) {
|
|
204
|
+
promise = new Promise<Block.Block<any, any, any, 1> | undefined>(
|
|
205
|
+
(resolve, reject) => {
|
|
206
|
+
const timeoutCallback = setTimeout(
|
|
207
|
+
() => {
|
|
208
|
+
resolve(undefined);
|
|
209
|
+
},
|
|
210
|
+
options.timeout || 30 * 1000
|
|
211
|
+
);
|
|
212
|
+
const abortHandler = () => {
|
|
213
|
+
clearTimeout(timeoutCallback);
|
|
214
|
+
this._resolvers.delete(cidString);
|
|
215
|
+
this.closeController.signal.removeEventListener(
|
|
216
|
+
"abort",
|
|
217
|
+
abortHandler
|
|
218
|
+
);
|
|
219
|
+
reject(new AbortError());
|
|
220
|
+
};
|
|
221
|
+
this.closeController.signal.addEventListener("abort", abortHandler);
|
|
222
|
+
|
|
223
|
+
this._resolvers.set(cidString, async (bytes: Uint8Array) => {
|
|
224
|
+
const value = await checkDecodeBlock(cidObject, bytes, {
|
|
225
|
+
codec,
|
|
226
|
+
hasher: options?.hasher
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
clearTimeout(timeoutCallback);
|
|
230
|
+
this._resolvers.delete(cidString); // TODO concurrency might not work as expected here
|
|
231
|
+
this.closeController.signal.removeEventListener(
|
|
232
|
+
"abort",
|
|
233
|
+
abortHandler
|
|
234
|
+
);
|
|
235
|
+
resolve(value);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
this._readFromPeersPromises.set(cidString, promise);
|
|
241
|
+
|
|
242
|
+
const publish = (to: string) => {
|
|
243
|
+
if (!options?.from || options.from.includes(to))
|
|
244
|
+
this.options.publish(new BlockRequest(cidString), { to: [to] });
|
|
245
|
+
};
|
|
246
|
+
|
|
247
|
+
const publishOnNewPeers = (e: CustomEvent<PublicSignKey>) => {
|
|
248
|
+
return publish(e.detail.hashcode());
|
|
249
|
+
};
|
|
250
|
+
this._events.addEventListener("peer:reachable", publishOnNewPeers);
|
|
251
|
+
this.options.publish(new BlockRequest(cidString), {
|
|
252
|
+
to: options.from
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// we want to make sure that if some new peers join, we also try to ask them
|
|
256
|
+
|
|
257
|
+
const result = await promise;
|
|
258
|
+
this._readFromPeersPromises.delete(cidString);
|
|
259
|
+
|
|
260
|
+
// stop asking new peers, because we already got an response
|
|
261
|
+
this._events.removeEventListener("peer:reachable", publishOnNewPeers);
|
|
262
|
+
return result?.bytes;
|
|
263
|
+
} else {
|
|
264
|
+
const result = await promise;
|
|
265
|
+
return result?.bytes;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async stop(): Promise<void> {
|
|
270
|
+
// Dont listen for more incoming messages
|
|
271
|
+
|
|
272
|
+
// Wait for processing request
|
|
273
|
+
this.closeController.abort();
|
|
274
|
+
this._loadFetchQueue.clear();
|
|
275
|
+
await this._loadFetchQueue.onIdle(); // wait for pending
|
|
276
|
+
await this.localStore?.stop();
|
|
277
|
+
this._readFromPeersPromises.clear();
|
|
278
|
+
this._resolvers.clear();
|
|
279
|
+
this._open = false;
|
|
280
|
+
// we dont cleanup subscription because we dont know if someone else is sbuscribing also
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
waitFor(peer: PeerId | PublicSignKey): Promise<void> {
|
|
284
|
+
return this.options.waitFor(peer);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async size() {
|
|
288
|
+
return this.localStore.size();
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
get status() {
|
|
292
|
+
if (this._open) {
|
|
293
|
+
return this.localStore?.status();
|
|
294
|
+
} else {
|
|
295
|
+
return "closed";
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
package/lib/esm/level.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"level.js","sourceRoot":"","sources":["../../src/level.ts"],"names":[],"mappings":"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"}
|
package/lib/esm/store.js
DELETED
package/lib/esm/store.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/store.ts"],"names":[],"mappings":""}
|
package/lib/esm/streams.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const x = 123;
|
package/lib/esm/streams.js
DELETED
package/lib/esm/streams.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"streams.js","sourceRoot":"","sources":["../../src/streams.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC"}
|
package/src/streams.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export const x = 123;
|