Skip to content
This repository has been archived by the owner on Jun 6, 2024. It is now read-only.

[Feature Request] Add KV list method #130

Open
GregBrimble opened this issue Oct 27, 2019 · 2 comments
Open

[Feature Request] Add KV list method #130

GregBrimble opened this issue Oct 27, 2019 · 2 comments

Comments

@GregBrimble
Copy link
Contributor

KV namespaces now support the list() method which returns a paginated list of keys: https://developers.cloudflare.com/workers/reference/storage/listing-keys/.

This method is missing from the KeyValueStore class.

@GregBrimble
Copy link
Contributor Author

GregBrimble commented Oct 27, 2019

I've personally being using this shim:

// namespace.test.ts

/* eslint-disable @typescript-eslint/camelcase */
import Cloudworker from '@dollarshaveclub/cloudworker'

const LIST_MAX_LIMIT = 1000

const namespace = new (Cloudworker as any).KeyValueStore()
namespace.list = async function(
  this,
  {
    limit = 1000,
    prefix = ``,
    cursor = `-1`,
  }: {
    prefix?: string
    limit?: number
    cursor?: string
  }
): Promise<{
  keys: {
    name: string
    expiration?: number
  }[]
  list_complete: boolean
  cursor: string
}> {
  if (limit > LIST_MAX_LIMIT) limit = LIST_MAX_LIMIT
  if (limit < 0) limit = 0

  const { store } = this

  let keys = Array.from(store.keys() as string[]).filter((key: string) =>
    key.startsWith(prefix)
  )

  keys = keys.slice(+cursor + 1)

  const list_complete = keys.length <= limit

  keys = keys.slice(0, limit)

  const nextCursor = (
    +cursor + (list_complete ? keys.length : limit)
  ).toString()

  return Promise.resolve({
    keys: keys.map(key => ({
      name: key,
    })),
    list_complete,
    cursor: nextCursor,
  })
}

export { namespace }

If there is interest, I'm more than happy to write up a PR. The only concern I have is with the expiration part of the response. This hasn't been implemented in KeyValueStore yet, so I've just been dropping it from the response.

I also don't know how Cloudflare are generating the cursors they use (e.g. 6Ck1la0VxJ0djhidm1MdX2FyD), so I've been using the index of the (ordered) map, which seems to work for testing.

@iameli
Copy link

iameli commented Dec 29, 2019

This looks solid!

I also don't know how Cloudflare are generating the cursors they use (e.g. 6Ck1la0VxJ0djhidm1MdX2FyD), so I've been using the index of the (ordered) map, which seems to work for testing.

The main thing to verify here would be the behavior of the cursors when there's lots of insertions in between list operations. I slightly suspect that Cloudflare's cursors use the last key of the previous "page" as a starting point for the next page rather than its global order, but I haven't verified this experimentally.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants