storage icon indicating copy to clipboard operation
storage copied to clipboard

bug: zrange rev flag causes empty return list / flaky zrange

Open benheckmann opened this issue 1 year ago • 2 comments

Hi,

When using kv.zrange, the same input sometimes returns the list of values, and sometimes an empty list. When using the cli on Vercel, I always get the list.

export async function getChats(userId?: string | null) {
  const session = await auth()

  if (!userId) {
    return []
  }

  if (userId !== session?.user?.id) {
    return {
      error: 'Unauthorized'
    }
  }

  try {
    const chats: string[] = await kv.zrange(`user:chat:${userId}`, 0, -1, {
      rev: true
    })
    
    const pipeline = kv.pipeline()
    for (const chat of chats) {
      pipeline.hgetall(chat)
    }
    const results = await pipeline.exec()

    return results as Chat[]
  } catch (error) {
    return []
  }
}

I have used the debugger to make sure that the userId is the same in both cases and it passes the authentication check. However, chats sometimes evaluates to an empty list, when it should have the values I get using the cli. This is right below the line, so its not that there is an error thrown.

Not sure if this is an issue with the package or if I'm just unable to find out what the difference in the calls is when it works. In this case: is it possible to activate some sort of logging?

benheckmann avatar Aug 24 '24 21:08 benheckmann

Update: I have done some more tests and find that the {rev: true} option causes this specific issue.

Here are some examples of what the cli returns vs what the node sdk returns.

CLI:

➜ zrange user:chat:1 0 -1 rev
chat:C9Osv8r, chat:v3XkExq, chat:yjFBYAv, chat:oSSCC6g, chat:GLcQnjN, chat:cCmsDo5, chat:2WR6JPL, chat:SPPpe8H, chat:fvgQqRz, chat:qDL4ITh, chat:kAlLWwR, chat:e13tXFh
➜ zrange user:chat:29d2f72f-46a9-4137-9198-436f3194f64c 0 -1 rev
chat:Ax30Fwb, chat:IhvC1Na, chat:Ph9PXVN, chat:aaPtIoD
➜ zrange user:chat:1 0 -1
chat:e13tXFh, chat:kAlLWwR, chat:qDL4ITh, chat:fvgQqRz, chat:SPPpe8H, chat:2WR6JPL, chat:cCmsDo5, chat:GLcQnjN, chat:oSSCC6g, chat:yjFBYAv, chat:v3XkExq, chat:C9Osv8r
➜ zrange user:chat:29d2f72f-46a9-4137-9198-436f3194f64c 0 -1
chat:aaPtIoD, chat:Ph9PXVN, chat:IhvC1Na, chat:Ax30Fwb

Node:

const key1 = "user:chat:1"
const key2 = "user:chat:29d2f72f-46a9-4137-9198-436f3194f64c"
const chats1: string[] = await kv.zrange(key1, 0, -1, { rev: true }) // returns Array(0) >> but should be returning Array(12)
const chats2: string[] = await kv.zrange(key2, 0, -1, { rev: true }) // returns Array(4)
const chats1NoRev: string[] = await kv.zrange(key1, 0, -1) // returns Array(12)
const chats2NoRev: string[] = await kv.zrange(key2, 0, -1) // returns Array(4)

const keyExists = await kv.exists(key1) // returns 1
const keyType = await kv.type(key1) // returns zset
const setSize = await kv.zcard(key1) // returns 12

For now, I will just omit the rev option and reverse the list myself.

benheckmann avatar Aug 25 '24 09:08 benheckmann

I have done some more tests and keep running into situations with unexpected behavior. For instance,

const chats: string[] = await kv.zrange(`user:chat:${userId}`, 0, -1)

sometimes returns an empty array, while

const chats: string[] = await kv.zrange(`user:chat:${userId}`, 0, 3)

is not empty.

benheckmann avatar Aug 28 '24 15:08 benheckmann