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
}
}
}
}```