diff --git a/packages/interface/src/routing.ts b/packages/interface/src/routing.ts index 7263e4f1..1ab5ed5f 100644 --- a/packages/interface/src/routing.ts +++ b/packages/interface/src/routing.ts @@ -64,6 +64,19 @@ export interface Routing { */ provide(cid: CID, options?: RoutingOptions): Promise + /** + * Helia will periodically re-provide every previously provided CID. Use this + * method to no longer re-provide the passed CID. + * + * @example + * + * ```js + * // ... + * await contentRouting.cancelReprovide(cid) + * ``` + */ + cancelReprovide(key: CID, options?: AbortOptions): Promise + /** * Find the providers of the passed CID. * diff --git a/packages/routers/src/delegated-http-routing.ts b/packages/routers/src/delegated-http-routing.ts index 6cb30e9a..d9e9da9b 100644 --- a/packages/routers/src/delegated-http-routing.ts +++ b/packages/routers/src/delegated-http-routing.ts @@ -25,11 +25,15 @@ class DelegatedHTTPRouter implements Routing { this.client = createDelegatedRoutingV1HttpApiClient(url, init) } - async provide (cid: CID, options?: RoutingOptions | undefined): Promise { + async provide (cid: CID, options?: RoutingOptions): Promise { // noop } - async * findProviders (cid: CID, options?: RoutingOptions | undefined): AsyncIterable { + async cancelReprovide (cid?: CID, options?: RoutingOptions): Promise { + // noop + } + + async * findProviders (cid: CID, options?: RoutingOptions): AsyncIterable { yield * map(this.client.getProviders(cid, options), (record) => { return { id: record.ID, @@ -39,7 +43,7 @@ class DelegatedHTTPRouter implements Routing { }) } - async put (key: Uint8Array, value: Uint8Array, options?: RoutingOptions | undefined): Promise { + async put (key: Uint8Array, value: Uint8Array, options?: RoutingOptions): Promise { if (!isIPNSKey(key)) { return } @@ -51,7 +55,7 @@ class DelegatedHTTPRouter implements Routing { await this.client.putIPNS(cid, record, options) } - async get (key: Uint8Array, options?: RoutingOptions | undefined): Promise { + async get (key: Uint8Array, options?: RoutingOptions): Promise { if (!isIPNSKey(key)) { throw new NotFoundError('Not found') } @@ -74,7 +78,7 @@ class DelegatedHTTPRouter implements Routing { } } - async findPeer (peerId: PeerId, options?: RoutingOptions | undefined): Promise { + async findPeer (peerId: PeerId, options?: RoutingOptions): Promise { const peer = await first(this.client.getPeers(peerId, options)) if (peer != null) { @@ -87,7 +91,7 @@ class DelegatedHTTPRouter implements Routing { throw new NotFoundError('Not found') } - async * getClosestPeers (key: Uint8Array, options?: RoutingOptions | undefined): AsyncIterable { + async * getClosestPeers (key: Uint8Array, options?: RoutingOptions): AsyncIterable { // noop } } diff --git a/packages/routers/src/libp2p-routing.ts b/packages/routers/src/libp2p-routing.ts index 935c86d4..e71cf7d1 100644 --- a/packages/routers/src/libp2p-routing.ts +++ b/packages/routers/src/libp2p-routing.ts @@ -13,6 +13,10 @@ class Libp2pRouter implements Routing { await this.libp2p.contentRouting.provide(cid, options) } + async cancelReprovide (key: CID, options?: RoutingOptions): Promise { + await this.libp2p.contentRouting.cancelReprovide(key, options) + } + async * findProviders (cid: CID, options?: RoutingOptions): AsyncIterable { yield * this.libp2p.contentRouting.findProviders(cid, options) } diff --git a/packages/routers/test/libp2p-routing.spec.ts b/packages/routers/test/libp2p-routing.spec.ts index d7c916d8..5309e858 100644 --- a/packages/routers/test/libp2p-routing.spec.ts +++ b/packages/routers/test/libp2p-routing.spec.ts @@ -33,6 +33,15 @@ describe('libp2p-routing', () => { expect(contentRouting.provide.calledWith(cid, options)).to.be.true() }) + it('should call through to contentRouting.cancelReprovide', async () => { + const cid = CID.parse('bafyreidykglsfhoixmivffc5uwhcgshx4j465xwqntbmu43nb2dzqwfvae') + const options = {} + + await router.cancelReprovide(cid, options) + + expect(contentRouting.cancelReprovide.calledWith(cid, options)).to.be.true() + }) + it('should call through to contentRouting.findProviders', async () => { contentRouting.findProviders.returns(async function * () {}()) diff --git a/packages/utils/src/routing.ts b/packages/utils/src/routing.ts index 11db18f6..47c33248 100644 --- a/packages/utils/src/routing.ts +++ b/packages/utils/src/routing.ts @@ -115,6 +115,15 @@ export class Routing implements RoutingInterface, Startable { ) } + async cancelReprovide (key: CID, options: AbortOptions = {}): Promise { + await Promise.all( + supports(this.routers, 'cancelReprovide') + .map(async (router) => { + await router.cancelReprovide(key, options) + }) + ) + } + /** * Store the given key/value pair in the available content routings */