Tom Redman
Tom Redman3w ago

Not sure why this is throwing a "multiple paginated queries" error

export const getJobsCountWithQueueAndStatus = internalQuery({
args: {
queue: v.string(),
status: v.union(
v.literal('pending'),
v.literal('processing'),
v.literal('completed'),
v.literal('failed'),
v.literal('cancelled'),
),
},
handler: async (ctx, { queue, status }) => {
let continueCursor = null;
let isDone = false;
let page;
const pageSize = 5;

let jobsCount = 0;

while (!isDone) {
console.log(queue, status);

({ continueCursor, isDone, page } = await ctx.db
.query('jobs')
.withIndex('by_queue_status', (q) => q.eq('queue', queue).eq('status', status))
.paginate({
cursor: continueCursor,
numItems: pageSize,
}));
jobsCount += page.length;
}

return jobsCount;
},
});
export const getJobsCountWithQueueAndStatus = internalQuery({
args: {
queue: v.string(),
status: v.union(
v.literal('pending'),
v.literal('processing'),
v.literal('completed'),
v.literal('failed'),
v.literal('cancelled'),
),
},
handler: async (ctx, { queue, status }) => {
let continueCursor = null;
let isDone = false;
let page;
const pageSize = 5;

let jobsCount = 0;

while (!isDone) {
console.log(queue, status);

({ continueCursor, isDone, page } = await ctx.db
.query('jobs')
.withIndex('by_queue_status', (q) => q.eq('queue', queue).eq('status', status))
.paginate({
cursor: continueCursor,
numItems: pageSize,
}));
jobsCount += page.length;
}

return jobsCount;
},
});
Schema:
jobs: defineTable({
args: v.any(),
attempt: v.number(),
dependencies: v.optional(v.array(v.id('jobs'))),
error: v.optional(
v.object({
attempt: v.number(),
message: v.string(),
stack: v.optional(v.string()),
timestamp: v.number(),
}),
),
fnArgs: v.any(),
fnHandle: v.string(),
fnName: v.string(),
fnType: v.union(v.literal('action'), v.literal('mutation'), v.literal('query')),
maxAttempts: v.number(),
metadata: v.optional(v.any()),
nextJobId: v.optional(v.id('jobs')),
priority: v.number(),
progress: v.optional(
v.object({
current: v.number(),
status: v.string(),
total: v.number(),
}),
),
queue: v.string(),
resourceRequirements: v.optional(
v.object({
cpu: v.number(),
memory: v.number(),
timeout: v.number(),
}),
),
result: v.optional(v.any()),
status: v.union(
v.literal('pending'),
v.literal('processing'),
v.literal('completed'),
v.literal('failed'),
v.literal('cancelled'),
),
timing: v.object({
completedAt: v.optional(v.number()),
createdAt: v.number(),
duration: v.optional(v.number()),
processingTime: v.optional(v.number()),
queueTime: v.optional(v.number()),
startedAt: v.optional(v.number()),
}),
}).index('by_queue_status', ['queue', 'status']),
jobs: defineTable({
args: v.any(),
attempt: v.number(),
dependencies: v.optional(v.array(v.id('jobs'))),
error: v.optional(
v.object({
attempt: v.number(),
message: v.string(),
stack: v.optional(v.string()),
timestamp: v.number(),
}),
),
fnArgs: v.any(),
fnHandle: v.string(),
fnName: v.string(),
fnType: v.union(v.literal('action'), v.literal('mutation'), v.literal('query')),
maxAttempts: v.number(),
metadata: v.optional(v.any()),
nextJobId: v.optional(v.id('jobs')),
priority: v.number(),
progress: v.optional(
v.object({
current: v.number(),
status: v.string(),
total: v.number(),
}),
),
queue: v.string(),
resourceRequirements: v.optional(
v.object({
cpu: v.number(),
memory: v.number(),
timeout: v.number(),
}),
),
result: v.optional(v.any()),
status: v.union(
v.literal('pending'),
v.literal('processing'),
v.literal('completed'),
v.literal('failed'),
v.literal('cancelled'),
),
timing: v.object({
completedAt: v.optional(v.number()),
createdAt: v.number(),
duration: v.optional(v.number()),
processingTime: v.optional(v.number()),
queueTime: v.optional(v.number()),
startedAt: v.optional(v.number()),
}),
}).index('by_queue_status', ['queue', 'status']),
Error:
Error: [CONVEX Q(jobs/jobQueue:getJobsCountWithQueueAndStatus)] [Request ID: e735d416db91c2a6] Server Error
Uncaught Error: This query or mutation function ran multiple paginated queries. Convex only supports a single paginated query in each function.
at async handler (../../convex/jobs/jobQueue.ts:54:18)

Called by client
Error: [CONVEX Q(jobs/jobQueue:getJobsCountWithQueueAndStatus)] [Request ID: e735d416db91c2a6] Server Error
Uncaught Error: This query or mutation function ran multiple paginated queries. Convex only supports a single paginated query in each function.
at async handler (../../convex/jobs/jobQueue.ts:54:18)

Called by client
Calling once with arguments:
{
queue: "instagramApi",
status: "completed",
}
{
queue: "instagramApi",
status: "completed",
}
6 Replies
Convex Bot
Convex Bot3w ago
Thanks for posting in <#1088161997662724167>. Reminder: If you have a Convex Pro account, use the Convex Dashboard to file support tickets. - Provide context: What are you trying to achieve, what is the end-user interaction, what are you seeing? (full error message, command output, etc.) - Use search.convex.dev to search Docs, Stack, and Discord all at once. - Additionally, you can post your questions in the Convex Community's <#1228095053885476985> channel to receive a response from AI. - Avoid tagging staff unless specifically instructed. Thank you!
erquhart
erquhart3w ago
The query is calling paginate() multiple times, it can only be called once per convex query function invoication So you'll want to have a query that accepts pagination options as args, so that query can be called once per page You can turn the query function there into an action, and then split out the pagination part to a query, and the action will be able to loop over the pages and call the query the way you're expecting
RJ
RJ3w ago
I would guess that the idea behind this limitation is that otherwise, using paginate to iterate through all of the documents in a table like this would be basically equivalent to doing myQuery.collect(), with the same shortcomings. So the (implicit) suggestion is to either just use collect(), or break it up across multiple Convex functions
Tom Redman
Tom RedmanOP3w ago
Ahh thank you @erquhart! Makes sense, if a little unintuitive. I guess I can't paginate through a table in its own query.
erquhart
erquhart3w ago
Yeah, I've definitely tried to do this before lol

Did you find this page helpful?