Asjas/prisma-redis-middleware

Forever Pending Response When Using Limit Filter Inside Transaction

ernestasga opened this issue · 1 comments

rDescribe the bug
When using a transaction of two parts (count and findMany) the result never comes back, if skip parameter is specified and is greater than 0. If skip is 0, the result comes back as expected. If skip is not specified, the result comes back as expected. This makes pagination totally unusable.

To Reproduce
Request a transaction with a count and a findMany. The findMany should have a limit and a skip parameter. The skip parameter should be greater than 0. The result will never come back.
Hears an example function from my application that demonstrates the issue:

export const getTeams = async (
  filter?: PaginationDataFilter
): Promise<PaginationData<Team>> => {
  try {
    const result = await prisma.$transaction([
      prisma.team.count({
        where: {
          ...(((filter?.search) != null) && {
            OR: [
              { name: { contains: filter?.search, mode: 'insensitive' } },
              { description: { contains: filter?.search, mode: 'insensitive' } }
            ]
          })
        }
      }),
      prisma.team.findMany({
        where: {
          ...(((filter?.search) != null) && {
            OR: [
              { name: { contains: filter?.search, mode: 'insensitive' } },
              { description: { contains: filter?.search, mode: 'insensitive' } }
            ]
          })
        },
        ...(((filter?.limit) != null) ? { take: +filter?.limit } : {}),
        ...(((filter?.limit) != null) && ((filter?.page) != null)
          ? {
              take: +filter?.limit,
              skip: +filter?.limit * (+filter?.page - 1)
            }
          : {}),
        ...(((filter?.sort) != null) && { orderBy: { [filter?.sort.name]: filter?.sort.order } }),
        include: { members: true, invites: true, subscriptions: { include: { product: true } }, projects: true }
      })
    ])
    const response = {
      data: result[1],
      meta: {
        current_page: ((filter?.page) != null) ? filter?.page : 1,
        from: ((filter?.limit) != null) && ((filter?.page) != null) ? +filter?.limit * +filter?.page : 1,
        last_page: ((filter?.limit) != null) ? result[0] % +filter?.limit : 1,
        to: ((filter?.limit) != null) ? filter?.limit : result[0],
        total: result[0]
      }
    }
    utilLogger({ meta: { ...meta, function: 'getUsers' }, data: response })
    return response
  } catch (e) {
    utilLogger({ meta: { ...meta, function: 'getTeams' }, error: e })
    return {
      data: [],
      meta: {
        current_page: 1,
        from: 0,
        last_page: 1,
        to: 0,
        total: 0
      }
    }
  }
}
``


export interface PaginationDataFilter {
  page?: number
  limit?: number
  sort?: Sorting
  search?: string
}

Expected behavior
Return a paginated result based on all the filters provided.

Additional context
I suspect the problem may lie with the way this library handles transaction.

I simply refactored my code to not use transactions for fetching data. This solved the issue completely.

export const getTeams = async ({ filter, include }: {
  filter?: PaginationDataFilter
  include?: {
    members?: boolean
    invites?: boolean
    subscriptions?: {
      include?: {
        product?: boolean
      }
    }
    projects?: boolean
  }
}): Promise<PaginationData<Team>> => {
  try {
    const result: [number, Team[]] = [
      await prisma.team.count({
        where: {
          ...(((filter?.search) != null) && {
            OR: [
              { name: { contains: filter?.search, mode: 'insensitive' } },
              { description: { contains: filter?.search, mode: 'insensitive' } }
            ]
          })
        }
      }),
      await prisma.team.findMany({
        where: {
          ...(((filter?.search) != null) && {
            OR: [
              { name: { contains: filter?.search, mode: 'insensitive' } },
              { description: { contains: filter?.search, mode: 'insensitive' } }
            ]
          })
        },
        ...(((filter?.limit) != null) ? { take: +filter?.limit } : {}),
        ...(((filter?.limit) != null) && ((filter?.page) != null)
          ? {
              take: +filter?.limit,
              skip: +filter?.limit * (+filter?.page - 1)
            }
          : {}),
        ...(((filter?.sort) != null) && { orderBy: { [filter?.sort.name]: filter?.sort.order } }),
        include
      })
    ]
    const response = {
      data: result[1],
      meta: {
        current_page: ((filter?.page) != null) ? filter?.page : 1,
        from: ((filter?.limit) != null) && ((filter?.page) != null) ? +filter?.limit * +filter?.page : 1,
        last_page: ((filter?.limit) != null) ? result[0] % +filter?.limit : 1,
        to: ((filter?.limit) != null) ? filter?.limit : result[0],
        total: result[0]
      }
    }
    utilLogger({ meta: { ...meta, function: 'getUsers' }, data: response })
    return response
  } catch (e) {
    utilLogger({ meta: { ...meta, function: 'getTeams' }, error: e })
    return {
      data: [],
      meta: {
        current_page: 1,
        from: 0,
        last_page: 1,
        to: 0,
        total: 0
      }
    }
  }
}```