Skip to content

Commit

Permalink
feat: allow updating pin metadata (#647)
Browse files Browse the repository at this point in the history
Adds a `setMetadata` method to the pins interface to allow updating
pin metadata, also a `.get` method to retrieve data for a specific
pin.
  • Loading branch information
achingbrain authored Oct 7, 2024
1 parent 60d8c8a commit bc64f47
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
19 changes: 15 additions & 4 deletions packages/interface/src/pins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,14 @@ export interface IsPinnedOptions extends AbortOptions {

export interface Pins {
/**
* Pin a block in the blockstore. It will not be deleted
* when garbage collection is run.
* Pin a block in the blockstore. It will not be deleted when garbage
* collection is run.
*/
add(cid: CID, options?: AddOptions): AsyncGenerator<CID, void, undefined>

/**
* Unpin the block that corresponds to the passed CID. The block will
* be deleted when garbage collection is run.
* Unpin the block that corresponds to the passed CID. The block will be
* deleted when garbage collection is run.
*/
rm(cid: CID, options?: RmOptions): AsyncGenerator<CID, void, undefined>

Expand All @@ -56,8 +56,19 @@ export interface Pins {
*/
ls(options?: LsOptions): AsyncGenerator<Pin, void, undefined>

/**
* If the CID is pinned, return details of the pin, otherwise throw an error
*/
get(cid: CID, options?: AbortOptions): Promise<Pin>

/**
* Return true if the passed CID is pinned
*/
isPinned(cid: CID, options?: IsPinnedOptions): Promise<boolean>

/**
* If the CID is pinned, update the metadata associated with the pin,
* otherwise throw an error
*/
setMetadata(cid: CID, metadata: Record<string, string | number | boolean> | undefined, options?: AbortOptions): Promise<void>
}
17 changes: 17 additions & 0 deletions packages/utils/src/pins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,4 +221,21 @@ export class PinsImpl implements Pins {

return this.datastore.has(blockKey, options)
}

async get (cid: CID, options?: AbortOptions): Promise<Pin> {
const pinKey = toDSKey(cid)
const buf = await this.datastore.get(pinKey, options)

return cborg.decode(buf)
}

async setMetadata (cid: CID, metadata: Record<string, string | number | boolean> | undefined, options?: AbortOptions): Promise<void> {
const pinKey = toDSKey(cid)
const buf = await this.datastore.get(pinKey, options)
const pin: DatastorePin = cborg.decode(buf)

pin.metadata = metadata ?? {}

await this.datastore.put(pinKey, cborg.encode(pin), options)
}
}
33 changes: 33 additions & 0 deletions packages/utils/test/pins.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,39 @@ describe('pins', () => {
await expect(helia.pins.isPinned(cidV0)).to.eventually.be.true('did not pin v0 CID')
})

it('gets a pin', async () => {
const cid = await createAndPutBlock(raw.code, Uint8Array.from([0, 1, 2, 3]), helia.blockstore)

await drain(helia.pins.add(cid))

const pin = await helia.pins.get(cid)

expect(pin).to.have.property('depth', Infinity)
expect(pin).to.have.deep.property('metadata', {})
})

it('updates metadata for a pin', async () => {
const cid = await createAndPutBlock(raw.code, Uint8Array.from([0, 1, 2, 3]), helia.blockstore)

await drain(helia.pins.add(cid))

const pin = await helia.pins.get(cid)

expect(pin).to.have.deep.property('metadata', {})

const newMetadata = {
foo: 'bar',
baz: true,
qux: 5
}

await helia.pins.setMetadata(cid, newMetadata)

const updatedPin = await helia.pins.get(cid)

expect(updatedPin).to.have.deep.property('metadata', newMetadata)
})

it('pins a block with progress events', async () => {
const cidV1 = await createAndPutBlock(raw.code, Uint8Array.from([0, 1, 2, 3]), helia.blockstore)

Expand Down

0 comments on commit bc64f47

Please sign in to comment.