@helia/utils 2.5.2-73a28eda → 2.5.2-9114743f
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/index.min.js +22 -2
- package/dist/index.min.js.map +4 -4
- package/dist/src/abstract-session.d.ts +3 -3
- package/dist/src/abstract-session.d.ts.map +1 -1
- package/dist/src/abstract-session.js.map +1 -1
- package/dist/src/graph-walker.d.ts +3 -21
- package/dist/src/graph-walker.d.ts.map +1 -1
- package/dist/src/graph-walker.js +20 -17
- package/dist/src/graph-walker.js.map +1 -1
- package/dist/src/index.d.ts +30 -37
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +54 -29
- package/dist/src/index.js.map +1 -1
- package/dist/src/pins.d.ts.map +1 -1
- package/dist/src/pins.js +11 -39
- package/dist/src/pins.js.map +1 -1
- package/dist/src/routing.d.ts +7 -5
- package/dist/src/routing.d.ts.map +1 -1
- package/dist/src/routing.js +10 -4
- package/dist/src/routing.js.map +1 -1
- package/dist/src/utils/is-cid.d.ts +3 -0
- package/dist/src/utils/is-cid.d.ts.map +1 -0
- package/dist/src/utils/is-cid.js +8 -0
- package/dist/src/utils/is-cid.js.map +1 -0
- package/dist/src/utils/networked-storage.d.ts +2 -1
- package/dist/src/utils/networked-storage.d.ts.map +1 -1
- package/dist/src/utils/networked-storage.js.map +1 -1
- package/dist/src/utils/session-storage.d.ts +2 -2
- package/dist/src/utils/session-storage.d.ts.map +1 -1
- package/dist/src/utils/session-storage.js.map +1 -1
- package/package.json +19 -19
- package/src/abstract-session.ts +4 -4
- package/src/graph-walker.ts +30 -43
- package/src/index.ts +89 -74
- package/src/pins.ts +12 -50
- package/src/routing.ts +23 -10
- package/src/utils/is-cid.ts +9 -0
- package/src/utils/networked-storage.ts +2 -1
- package/src/utils/session-storage.ts +2 -2
package/src/index.ts
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { keychain } from '@ipshipyard/keychain'
|
|
9
|
-
import {
|
|
9
|
+
import { start, stop, TypedEventEmitter } from '@libp2p/interface'
|
|
10
10
|
import { dns } from '@multiformats/dns'
|
|
11
|
+
import { defaultLogger } from 'birnam'
|
|
12
|
+
import { MemoryBlockstore } from 'blockstore-core'
|
|
13
|
+
import { MemoryDatastore } from 'datastore-core'
|
|
11
14
|
import drain from 'it-drain'
|
|
12
15
|
import { CustomProgressEvent } from 'progress-events'
|
|
13
16
|
import { PinsImpl } from './pins.ts'
|
|
@@ -19,15 +22,14 @@ import { getCrypto } from './utils/get-crypto.ts'
|
|
|
19
22
|
import { getHasher } from './utils/get-hasher.ts'
|
|
20
23
|
import { NetworkedStorage } from './utils/networked-storage.ts'
|
|
21
24
|
import type { BlockStorageInit } from './storage.ts'
|
|
22
|
-
import type { CodecLoader, GCOptions, HasherLoader, Helia as HeliaInterface, HeliaEvents, Routing, CryptoLoader, Crypto } from '@helia/interface'
|
|
25
|
+
import type { CodecLoader, GCOptions, HasherLoader, Helia as HeliaInterface, HeliaEvents, Routing, CryptoLoader, Crypto, NodeInfo, Router, HeliaMixin } from '@helia/interface'
|
|
23
26
|
import type { BlockBroker } from '@helia/interface/blocks'
|
|
24
27
|
import type { Pins } from '@helia/interface/pins'
|
|
25
28
|
import type { Keychain, KeychainInit } from '@ipshipyard/keychain'
|
|
26
|
-
import type { ComponentLogger,
|
|
29
|
+
import type { ComponentLogger, Logger, Metrics } from '@libp2p/interface'
|
|
27
30
|
import type { DNS } from '@multiformats/dns'
|
|
28
31
|
import type { Blockstore } from 'interface-blockstore'
|
|
29
32
|
import type { Datastore } from 'interface-datastore'
|
|
30
|
-
import type { Libp2pOptions } from 'libp2p'
|
|
31
33
|
import type { BlockCodec } from 'multiformats'
|
|
32
34
|
import type { CID } from 'multiformats/cid'
|
|
33
35
|
import type { MultihashHasher } from 'multiformats/hashes/interface'
|
|
@@ -35,6 +37,8 @@ import type { MultihashHasher } from 'multiformats/hashes/interface'
|
|
|
35
37
|
export { AbstractSession } from './abstract-session.ts'
|
|
36
38
|
export type { AbstractCreateSessionOptions, BlockstoreSessionEvents, AbstractSessionComponents } from './abstract-session.ts'
|
|
37
39
|
|
|
40
|
+
export { isCID } from './utils/is-cid.ts'
|
|
41
|
+
|
|
38
42
|
export type { BlockStorage, BlockStorageInit }
|
|
39
43
|
|
|
40
44
|
export { breadthFirstWalker, depthFirstWalker, naturalOrderWalker } from './graph-walker.ts'
|
|
@@ -43,26 +47,7 @@ export type { GraphWalkerComponents, GraphWalkerInit, GraphNode, GraphWalker } f
|
|
|
43
47
|
/**
|
|
44
48
|
* Options used to create a Helia node.
|
|
45
49
|
*/
|
|
46
|
-
export interface HeliaInit
|
|
47
|
-
/**
|
|
48
|
-
* A libp2p node is required to perform network operations. Either a
|
|
49
|
-
* pre-configured node or options to configure a node can be passed
|
|
50
|
-
* here.
|
|
51
|
-
*
|
|
52
|
-
* If node options are passed, they will be merged with the default
|
|
53
|
-
* config for the current platform. In this case all passed config
|
|
54
|
-
* keys will replace those from the default config.
|
|
55
|
-
*
|
|
56
|
-
* The libp2p `start` option is not supported, instead please pass `start` in
|
|
57
|
-
* the root of the HeliaInit object.
|
|
58
|
-
*/
|
|
59
|
-
libp2p: T | Omit<Libp2pOptions<any>, 'start'>
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Pass `false` to not start the Helia node
|
|
63
|
-
*/
|
|
64
|
-
start?: boolean
|
|
65
|
-
|
|
50
|
+
export interface HeliaInit {
|
|
66
51
|
/**
|
|
67
52
|
* By default Helia stores the node's PeerId in an encrypted form in a
|
|
68
53
|
* libp2p keystore. These options control how that keystore is configured.
|
|
@@ -72,12 +57,12 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
|
|
|
72
57
|
/**
|
|
73
58
|
* The blockstore is where blocks are stored
|
|
74
59
|
*/
|
|
75
|
-
blockstore
|
|
60
|
+
blockstore?: Blockstore
|
|
76
61
|
|
|
77
62
|
/**
|
|
78
63
|
* The datastore is where data is stored
|
|
79
64
|
*/
|
|
80
|
-
datastore
|
|
65
|
+
datastore?: Datastore
|
|
81
66
|
|
|
82
67
|
/**
|
|
83
68
|
* By default sha256, sha512 and identity hashes are supported for
|
|
@@ -105,12 +90,6 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
|
|
|
105
90
|
*/
|
|
106
91
|
loadCodec?(code: number): BlockCodec<any, any> | Promise<BlockCodec<any, any>>
|
|
107
92
|
|
|
108
|
-
/**
|
|
109
|
-
* A list of strategies used to fetch blocks when they are not present in
|
|
110
|
-
* the local blockstore
|
|
111
|
-
*/
|
|
112
|
-
blockBrokers: Array<(components: any) => BlockBroker>
|
|
113
|
-
|
|
114
93
|
/**
|
|
115
94
|
* A list of pre-supported public/private key implementations
|
|
116
95
|
*/
|
|
@@ -143,11 +122,17 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
|
|
|
143
122
|
*/
|
|
144
123
|
logger?: ComponentLogger
|
|
145
124
|
|
|
125
|
+
/**
|
|
126
|
+
* A list of strategies used to fetch blocks when they are not present in
|
|
127
|
+
* the local blockstore
|
|
128
|
+
*/
|
|
129
|
+
blockBrokers?: Array<BlockBroker | ((components: any) => BlockBroker)>
|
|
130
|
+
|
|
146
131
|
/**
|
|
147
132
|
* Routers perform operations such as looking up content providers,
|
|
148
133
|
* information about network peers or getting/putting records.
|
|
149
134
|
*/
|
|
150
|
-
routers?: Array<
|
|
135
|
+
routers?: Array<Router | ((components: any) => Router)>
|
|
151
136
|
|
|
152
137
|
/**
|
|
153
138
|
* During provider lookups, peers can be returned from routing implementations
|
|
@@ -192,7 +177,6 @@ export interface HeliaInit<T extends Libp2p = Libp2p> {
|
|
|
192
177
|
}
|
|
193
178
|
|
|
194
179
|
interface Components {
|
|
195
|
-
libp2p: Libp2p
|
|
196
180
|
blockstore: Blockstore
|
|
197
181
|
datastore: Datastore
|
|
198
182
|
logger: ComponentLogger
|
|
@@ -206,39 +190,46 @@ interface Components {
|
|
|
206
190
|
getCrypto: CryptoLoader
|
|
207
191
|
}
|
|
208
192
|
|
|
209
|
-
export class Helia
|
|
210
|
-
public
|
|
193
|
+
export class Helia implements HeliaInterface {
|
|
194
|
+
public info: NodeInfo
|
|
211
195
|
public blockstore: BlockStorage
|
|
212
196
|
public datastore: Datastore
|
|
213
|
-
public events: TypedEventEmitter<HeliaEvents<
|
|
197
|
+
public events: TypedEventEmitter<HeliaEvents<this>>
|
|
214
198
|
public pins: Pins
|
|
215
199
|
public logger: ComponentLogger
|
|
216
|
-
public routing:
|
|
200
|
+
public routing: RoutingClass
|
|
217
201
|
public getCodec: CodecLoader
|
|
218
202
|
public getHasher: HasherLoader
|
|
219
203
|
public getCrypto: CryptoLoader
|
|
220
204
|
public dns: DNS
|
|
221
205
|
public keychain: Keychain
|
|
222
206
|
public metrics?: Metrics
|
|
207
|
+
public status: 'stopped' | 'stopping' | 'starting' | 'started'
|
|
223
208
|
private readonly log: Logger
|
|
209
|
+
private readonly blockBrokers: BlockBroker[]
|
|
210
|
+
private readonly mixins: HeliaMixin[]
|
|
224
211
|
|
|
225
|
-
constructor (init:
|
|
226
|
-
this.
|
|
212
|
+
constructor (init: HeliaInit & { name: string, version: string }) {
|
|
213
|
+
this.info = {
|
|
214
|
+
name: init.name,
|
|
215
|
+
version: init.version
|
|
216
|
+
}
|
|
217
|
+
this.logger = init.logger ?? defaultLogger()
|
|
227
218
|
this.log = this.logger.forComponent('helia')
|
|
228
219
|
this.getHasher = getHasher(init.hashers, init.loadHasher)
|
|
229
220
|
this.getCodec = getCodec(init.codecs, init.loadCodec)
|
|
230
221
|
this.getCrypto = getCrypto(init.cryptos, init.loadCrypto)
|
|
231
222
|
this.dns = init.dns ?? dns()
|
|
232
223
|
this.metrics = init.metrics
|
|
233
|
-
this.
|
|
234
|
-
this.
|
|
224
|
+
this.events = new TypedEventEmitter<HeliaEvents<typeof this>>()
|
|
225
|
+
this.status = 'stopped'
|
|
226
|
+
this.mixins = []
|
|
235
227
|
|
|
236
228
|
// @ts-expect-error routing and keychain are not set
|
|
237
229
|
const components: Components = {
|
|
238
|
-
blockstore: init.blockstore,
|
|
239
|
-
datastore: init.datastore,
|
|
230
|
+
blockstore: init.blockstore ?? new MemoryBlockstore(),
|
|
231
|
+
datastore: init.datastore ?? new MemoryDatastore(),
|
|
240
232
|
logger: this.logger,
|
|
241
|
-
libp2p: this.libp2p,
|
|
242
233
|
blockBrokers: [],
|
|
243
234
|
getHasher: this.getHasher,
|
|
244
235
|
getCodec: this.getCodec,
|
|
@@ -251,7 +242,7 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
|
|
|
251
242
|
this.keychain = components.keychain = keychain()(components)
|
|
252
243
|
|
|
253
244
|
this.routing = components.routing = new RoutingClass(components, {
|
|
254
|
-
routers: (init.routers ?? []).flatMap((router:
|
|
245
|
+
routers: (init.routers ?? []).flatMap((router: Router | ((components: any) => Router)) => {
|
|
255
246
|
if (typeof router === 'function') {
|
|
256
247
|
router = router(components)
|
|
257
248
|
}
|
|
@@ -261,54 +252,86 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
|
|
|
261
252
|
router
|
|
262
253
|
]
|
|
263
254
|
|
|
264
|
-
// if the router provides a libp2p-style ContentRouter
|
|
265
|
-
const contentRouting = asContentRouting(router)
|
|
266
|
-
if (contentRouting != null) {
|
|
267
|
-
routers.push(contentRouting)
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// if the router provides a libp2p-style PeerRouter
|
|
271
|
-
const peerRouting = asPeerRouting(router)
|
|
272
|
-
if (peerRouting != null) {
|
|
273
|
-
routers.push(peerRouting)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
255
|
return routers
|
|
277
256
|
}),
|
|
278
257
|
providerLookupConcurrency: init.providerLookupConcurrency
|
|
279
258
|
})
|
|
280
259
|
|
|
281
|
-
components.blockBrokers = init.blockBrokers.map((
|
|
282
|
-
|
|
260
|
+
this.blockBrokers = components.blockBrokers = (init.blockBrokers ?? []).map((broker) => {
|
|
261
|
+
if (typeof broker === 'function') {
|
|
262
|
+
broker = broker(components)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
return broker
|
|
283
266
|
})
|
|
284
267
|
|
|
285
268
|
const networkedStorage = new NetworkedStorage(components, init)
|
|
286
|
-
this.pins = new PinsImpl(
|
|
269
|
+
this.pins = new PinsImpl(components.datastore, networkedStorage, this.getCodec)
|
|
287
270
|
this.blockstore = new BlockStorage(networkedStorage, this.pins, this.routing, {
|
|
288
271
|
holdGcLock: init.holdGcLock ?? true
|
|
289
272
|
})
|
|
290
|
-
this.datastore =
|
|
273
|
+
this.datastore = components.datastore
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
hasRouter (name: string): boolean {
|
|
277
|
+
return this.routing.hasRouter(name)
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
addRouter (router: Router): void {
|
|
281
|
+
this.routing.addRouter(router)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
hasBlockBroker (name: string): boolean {
|
|
285
|
+
return this.blockBrokers.findIndex(b => b.name === name) !== -1
|
|
291
286
|
}
|
|
292
287
|
|
|
293
|
-
|
|
288
|
+
addBlockBroker (blockBroker: BlockBroker): void {
|
|
289
|
+
this.blockBrokers.push(blockBroker)
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
addMixin (mixin: HeliaMixin): void {
|
|
293
|
+
this.mixins.push(mixin)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async start (): Promise<this> {
|
|
297
|
+
this.status = 'starting'
|
|
298
|
+
|
|
294
299
|
await assertDatastoreVersionIsCurrent(this.datastore)
|
|
295
300
|
await start(
|
|
296
301
|
this.blockstore,
|
|
297
302
|
this.datastore,
|
|
298
303
|
this.routing,
|
|
299
|
-
this.
|
|
304
|
+
...this.blockBrokers
|
|
300
305
|
)
|
|
306
|
+
|
|
307
|
+
for (const mixin of this.mixins) {
|
|
308
|
+
await mixin.start?.(this)
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
this.status = 'started'
|
|
301
312
|
this.events.dispatchEvent(new CustomEvent('start', { detail: this }))
|
|
313
|
+
|
|
314
|
+
return this
|
|
302
315
|
}
|
|
303
316
|
|
|
304
|
-
async stop (): Promise<
|
|
317
|
+
async stop (): Promise<this> {
|
|
318
|
+
this.status = 'stopping'
|
|
319
|
+
|
|
320
|
+
for (const mixin of this.mixins) {
|
|
321
|
+
await mixin.stop?.(this)
|
|
322
|
+
}
|
|
323
|
+
|
|
305
324
|
await stop(
|
|
306
325
|
this.blockstore,
|
|
307
326
|
this.datastore,
|
|
308
327
|
this.routing,
|
|
309
|
-
this.
|
|
328
|
+
...this.blockBrokers
|
|
310
329
|
)
|
|
330
|
+
|
|
331
|
+
this.status = 'stopped'
|
|
311
332
|
this.events.dispatchEvent(new CustomEvent('stop', { detail: this }))
|
|
333
|
+
|
|
334
|
+
return this
|
|
312
335
|
}
|
|
313
336
|
|
|
314
337
|
async gc (options: GCOptions = {}): Promise<void> {
|
|
@@ -343,11 +366,3 @@ export class Helia<T extends Libp2p> implements HeliaInterface<T> {
|
|
|
343
366
|
this.log('gc finished')
|
|
344
367
|
}
|
|
345
368
|
}
|
|
346
|
-
|
|
347
|
-
function asContentRouting (obj?: any): ContentRouting | undefined {
|
|
348
|
-
return obj?.[contentRoutingSymbol]
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
function asPeerRouting (obj?: any): PeerRouting | undefined {
|
|
352
|
-
return obj?.[peerRoutingSymbol]
|
|
353
|
-
}
|
package/src/pins.ts
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
import { InvalidParametersError } from '@libp2p/interface'
|
|
2
|
-
import { Queue } from '@libp2p/utils'
|
|
3
2
|
import * as cborg from 'cborg'
|
|
4
3
|
import { Key } from 'interface-datastore'
|
|
5
|
-
import toBuffer from 'it-to-buffer'
|
|
6
4
|
import { base36 } from 'multiformats/bases/base36'
|
|
7
|
-
import { createUnsafe } from 'multiformats/block'
|
|
8
5
|
import { CID } from 'multiformats/cid'
|
|
9
6
|
import { CustomProgressEvent } from 'progress-events'
|
|
10
7
|
import { equals as uint8ArrayEquals } from 'uint8arrays/equals'
|
|
11
8
|
import { AlreadyPinnedError } from './errors.ts'
|
|
9
|
+
import { depthFirstWalker } from './graph-walker.ts'
|
|
12
10
|
import type { CodecLoader } from '@helia/interface'
|
|
13
|
-
import type {
|
|
14
|
-
import type { AddOptions, AddPinEvents, IsPinnedOptions, LsOptions, Pin, Pins, RmOptions } from '@helia/interface/pins'
|
|
11
|
+
import type { AddOptions, IsPinnedOptions, LsOptions, Pin, Pins, RmOptions } from '@helia/interface/pins'
|
|
15
12
|
import type { AbortOptions } from '@libp2p/interface'
|
|
16
13
|
import type { Blockstore } from 'interface-blockstore'
|
|
17
14
|
import type { Datastore } from 'interface-datastore'
|
|
18
15
|
import type { Version } from 'multiformats/cid'
|
|
19
|
-
import type { ProgressOptions } from 'progress-events'
|
|
20
16
|
|
|
21
17
|
interface DatastorePin {
|
|
22
18
|
/**
|
|
@@ -49,11 +45,6 @@ interface WithPinnedBlockCallback {
|
|
|
49
45
|
const DATASTORE_PIN_PREFIX = '/pin/'
|
|
50
46
|
const DATASTORE_BLOCK_PREFIX = '/pinned-block/'
|
|
51
47
|
const DATASTORE_ENCODING = base36
|
|
52
|
-
const DAG_WALK_QUEUE_CONCURRENCY = 1
|
|
53
|
-
|
|
54
|
-
interface WalkDagOptions extends AbortOptions, ProgressOptions<GetBlockProgressEvents | AddPinEvents> {
|
|
55
|
-
depth: number
|
|
56
|
-
}
|
|
57
48
|
|
|
58
49
|
function toDSKey (cid: CID): Key {
|
|
59
50
|
if (cid.version === 0) {
|
|
@@ -87,15 +78,13 @@ export class PinsImpl implements Pins {
|
|
|
87
78
|
throw new InvalidParametersError('Depth must be greater than or equal to 0')
|
|
88
79
|
}
|
|
89
80
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
const walker = (options.walker ?? depthFirstWalker())({
|
|
82
|
+
blockstore: this.blockstore,
|
|
83
|
+
getCodec: this.getCodec
|
|
93
84
|
})
|
|
94
85
|
|
|
95
|
-
for await (const
|
|
96
|
-
|
|
97
|
-
depth
|
|
98
|
-
})) {
|
|
86
|
+
for await (const node of walker.walk(cid, { ...options, depth })) {
|
|
87
|
+
const childCid = node.block.cid
|
|
99
88
|
await this.#updatePinnedBlock(childCid, (pinnedBlock: DatastorePinnedBlock) => {
|
|
100
89
|
// do not update pinned block if this block is already pinned by this CID
|
|
101
90
|
if (pinnedBlock.pinnedBy.find(c => uint8ArrayEquals(c, cid.bytes)) != null) {
|
|
@@ -118,31 +107,6 @@ export class PinsImpl implements Pins {
|
|
|
118
107
|
await this.datastore.put(pinKey, cborg.encode(pin), options)
|
|
119
108
|
}
|
|
120
109
|
|
|
121
|
-
/**
|
|
122
|
-
* Walk a DAG in an iterable fashion
|
|
123
|
-
*/
|
|
124
|
-
async * #walkDag (cid: CID, queue: Queue<AsyncGenerator<CID>>, options: WalkDagOptions): AsyncGenerator<CID> {
|
|
125
|
-
if (options.depth === -1) {
|
|
126
|
-
return
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const codec = await this.getCodec(cid.code)
|
|
130
|
-
const bytes = await toBuffer(this.blockstore.get(cid, options))
|
|
131
|
-
const block = createUnsafe({ bytes, cid, codec })
|
|
132
|
-
|
|
133
|
-
yield cid
|
|
134
|
-
|
|
135
|
-
// walk dag, ensure all blocks are present
|
|
136
|
-
for (const [,cid] of block.links()) {
|
|
137
|
-
yield * await queue.add(async () => {
|
|
138
|
-
return this.#walkDag(cid, queue, {
|
|
139
|
-
...options,
|
|
140
|
-
depth: options.depth - 1
|
|
141
|
-
})
|
|
142
|
-
})
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
110
|
/**
|
|
147
111
|
* Update the pin count for the CID
|
|
148
112
|
*/
|
|
@@ -186,15 +150,13 @@ export class PinsImpl implements Pins {
|
|
|
186
150
|
|
|
187
151
|
await this.datastore.delete(pinKey, options)
|
|
188
152
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
153
|
+
const walker = (options.walker ?? depthFirstWalker())({
|
|
154
|
+
blockstore: this.blockstore,
|
|
155
|
+
getCodec: this.getCodec
|
|
192
156
|
})
|
|
193
157
|
|
|
194
|
-
for await (const
|
|
195
|
-
|
|
196
|
-
depth: pin.depth
|
|
197
|
-
})) {
|
|
158
|
+
for await (const node of walker.walk(cid, { ...options, depth: pin.depth })) {
|
|
159
|
+
const childCid = node.block.cid
|
|
198
160
|
await this.#updatePinnedBlock(childCid, (pinnedBlock): boolean => {
|
|
199
161
|
pinnedBlock.pinCount--
|
|
200
162
|
pinnedBlock.pinnedBy = pinnedBlock.pinnedBy.filter(c => uint8ArrayEquals(c, cid.bytes))
|
package/src/routing.ts
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
import { NoRoutersAvailableError } from '@helia/interface'
|
|
2
2
|
import { NotFoundError, start, stop } from '@libp2p/interface'
|
|
3
|
-
import {
|
|
3
|
+
import { Queue } from '@libp2p/utils'
|
|
4
4
|
import merge from 'it-merge'
|
|
5
5
|
import { CustomProgressEvent } from 'progress-events'
|
|
6
6
|
import { toString as uint8ArrayToString } from 'uint8arrays/to-string'
|
|
7
7
|
import { GetFailedError } from './errors.ts'
|
|
8
|
-
import type { Routing as RoutingInterface, Provider, RoutingOptions, RoutingFindProvidersProgressEvents, RoutingProvideProgressEvents, RoutingPutProgressEvents, RoutingGetProgressEvents, RoutingFindPeerProgressEvents, RoutingGetClosestPeersProgressEvents, RoutingCancelReprovideProgressEvents } from '@helia/interface'
|
|
9
|
-
import type { ComponentLogger, Logger, Metrics,
|
|
8
|
+
import type { Routing as RoutingInterface, Provider, RoutingOptions, RoutingFindProvidersProgressEvents, RoutingProvideProgressEvents, RoutingPutProgressEvents, RoutingGetProgressEvents, RoutingFindPeerProgressEvents, RoutingGetClosestPeersProgressEvents, RoutingCancelReprovideProgressEvents, Router, Peer } from '@helia/interface'
|
|
9
|
+
import type { ComponentLogger, Logger, Metrics, Startable } from '@libp2p/interface'
|
|
10
|
+
import type { AbortOptions } from 'abort-error'
|
|
10
11
|
import type { CID } from 'multiformats/cid'
|
|
11
12
|
|
|
12
13
|
const DEFAULT_PROVIDER_LOOKUP_CONCURRENCY = 5
|
|
13
14
|
|
|
14
15
|
export interface RoutingInit {
|
|
15
|
-
routers:
|
|
16
|
+
routers: Router[]
|
|
16
17
|
providerLookupConcurrency?: number
|
|
17
18
|
}
|
|
18
19
|
|
|
@@ -21,11 +22,15 @@ export interface RoutingComponents {
|
|
|
21
22
|
metrics?: Metrics
|
|
22
23
|
}
|
|
23
24
|
|
|
25
|
+
interface PeerQueueOptions extends AbortOptions {
|
|
26
|
+
peer: CID
|
|
27
|
+
}
|
|
28
|
+
|
|
24
29
|
export class Routing implements RoutingInterface, Startable {
|
|
25
30
|
public name: string
|
|
26
31
|
|
|
27
32
|
private readonly log: Logger
|
|
28
|
-
private readonly routers:
|
|
33
|
+
private readonly routers: Router[]
|
|
29
34
|
private readonly providerLookupConcurrency: number
|
|
30
35
|
|
|
31
36
|
constructor (components: RoutingComponents, init: RoutingInit) {
|
|
@@ -65,6 +70,14 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
65
70
|
await stop(...this.routers)
|
|
66
71
|
}
|
|
67
72
|
|
|
73
|
+
hasRouter (name: string): boolean {
|
|
74
|
+
return this.routers.findIndex(r => r.name === name) !== -1
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
addRouter (router: Router): void {
|
|
78
|
+
this.routers.push(router)
|
|
79
|
+
}
|
|
80
|
+
|
|
68
81
|
/**
|
|
69
82
|
* Iterates over all content routers in parallel to find providers of the
|
|
70
83
|
* given key
|
|
@@ -78,7 +91,7 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
78
91
|
// back as an empty array - when this happens we have to do a FIND_PEER
|
|
79
92
|
// query to get updated addresses, but we shouldn't block on this so use a
|
|
80
93
|
// separate bounded queue to perform this lookup
|
|
81
|
-
const queue = new
|
|
94
|
+
const queue = new Queue<Provider | null, PeerQueueOptions>({
|
|
82
95
|
concurrency: this.providerLookupConcurrency
|
|
83
96
|
})
|
|
84
97
|
|
|
@@ -145,7 +158,7 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
145
158
|
// have to refresh peer info for this peer to get updated multiaddrs
|
|
146
159
|
if (peer.multiaddrs.length === 0) {
|
|
147
160
|
// already looking this peer up
|
|
148
|
-
if (queue.find(peer.id) != null) {
|
|
161
|
+
if (queue.queue.find(job => job.options.peer.equals(peer.id)) != null) {
|
|
149
162
|
continue
|
|
150
163
|
}
|
|
151
164
|
|
|
@@ -167,7 +180,7 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
167
180
|
return null
|
|
168
181
|
}
|
|
169
182
|
}, {
|
|
170
|
-
|
|
183
|
+
peer: peer.id,
|
|
171
184
|
signal: options.signal
|
|
172
185
|
})
|
|
173
186
|
.catch(err => {
|
|
@@ -298,7 +311,7 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
298
311
|
/**
|
|
299
312
|
* Iterates over all peer routers in parallel to find the given peer
|
|
300
313
|
*/
|
|
301
|
-
async findPeer (id:
|
|
314
|
+
async findPeer (id: CID, options?: RoutingOptions<RoutingFindPeerProgressEvents>): Promise<Peer> {
|
|
302
315
|
if (this.routers.length === 0) {
|
|
303
316
|
throw new NoRoutersAvailableError('No peer routers available')
|
|
304
317
|
}
|
|
@@ -339,7 +352,7 @@ export class Routing implements RoutingInterface, Startable {
|
|
|
339
352
|
/**
|
|
340
353
|
* Attempt to find the closest peers on the network to the given key
|
|
341
354
|
*/
|
|
342
|
-
async * getClosestPeers (key: Uint8Array, options: RoutingOptions<RoutingGetClosestPeersProgressEvents> = {}): AsyncIterable<
|
|
355
|
+
async * getClosestPeers (key: Uint8Array, options: RoutingOptions<RoutingGetClosestPeersProgressEvents> = {}): AsyncIterable<Peer> {
|
|
343
356
|
if (this.routers.length === 0) {
|
|
344
357
|
throw new NoRoutersAvailableError('No peer routers available')
|
|
345
358
|
}
|
|
@@ -4,7 +4,8 @@ import { SessionStorage } from './session-storage.ts'
|
|
|
4
4
|
import { Storage } from './storage.ts'
|
|
5
5
|
import type { StorageComponents, StorageInit } from './storage.ts'
|
|
6
6
|
import type { BlockBroker, Blocks, CreateSessionOptions, SessionBlockstore } from '@helia/interface/blocks'
|
|
7
|
-
import type {
|
|
7
|
+
import type { Startable } from '@libp2p/interface'
|
|
8
|
+
import type { AbortOptions } from 'abort-error'
|
|
8
9
|
import type { Blockstore } from 'interface-blockstore'
|
|
9
10
|
import type { CID } from 'multiformats/cid'
|
|
10
11
|
|
|
@@ -3,7 +3,7 @@ import { anySignal } from 'any-signal'
|
|
|
3
3
|
import { Storage } from './storage.ts'
|
|
4
4
|
import type { StorageComponents } from './storage.ts'
|
|
5
5
|
import type { Pair, DeleteManyBlocksProgressEvents, DeleteBlockProgressEvents, GetBlockProgressEvents, GetManyBlocksProgressEvents, PutManyBlocksProgressEvents, PutBlockProgressEvents, GetAllBlocksProgressEvents, GetOfflineOptions, SessionBlockstore, SessionBlockBroker } from '@helia/interface/blocks'
|
|
6
|
-
import type { AbortOptions
|
|
6
|
+
import type { AbortOptions } from '@libp2p/interface'
|
|
7
7
|
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
8
8
|
import type { InputPair } from 'interface-blockstore'
|
|
9
9
|
import type { CID } from 'multiformats/cid'
|
|
@@ -35,7 +35,7 @@ export class SessionStorage extends Storage<SessionBlockBroker> implements Sessi
|
|
|
35
35
|
this.closeController.abort()
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
async addPeer (peer:
|
|
38
|
+
async addPeer (peer: CID | Multiaddr | Multiaddr[], options?: AbortOptions): Promise<void> {
|
|
39
39
|
await Promise.all(
|
|
40
40
|
this.blockBrokers
|
|
41
41
|
.map(broker => broker.addPeer(peer, options))
|