-
Notifications
You must be signed in to change notification settings - Fork 85
[7257] Add proper pagination to Hosted and Remote Instances pages + N+1 fix for Hosted Instances #7353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[7257] Add proper pagination to Hosted and Remote Instances pages + N+1 fix for Hosted Instances #7353
Changes from all commits
548ec55
db3cbbe
d4dba5e
8c9e889
1fc84e9
ff8f0cd
93e2ca8
c8eca28
ed63ccf
35ab9dc
10120d0
8372ee7
07b93f0
2c346e6
23e2812
b558e47
b5cbd25
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,30 +365,32 @@ module.exports = async function (app) { | |
| */ | ||
| app.get('/:teamId/projects', { | ||
| preHandler: app.needsPermission('team:projects:list'), | ||
| query: { | ||
| type: 'object', | ||
| properties: { | ||
| limit: { | ||
| type: 'number', | ||
| nullable: true | ||
| }, | ||
| includeMeta: { | ||
| type: 'boolean', | ||
| nullable: true, | ||
| default: false | ||
| }, | ||
| orderByMostRecentFlows: { | ||
| type: 'boolean', | ||
| nullable: true, | ||
| default: false | ||
| } | ||
| schema: { | ||
| query: { | ||
| allOf: [ | ||
| { $ref: 'PaginationParams' }, | ||
| { | ||
| type: 'object', | ||
| properties: { | ||
| sort: { | ||
| type: 'string', | ||
| enum: ['name', 'createdAt', 'updatedAt', 'application.name', 'flowLastUpdatedAt'] | ||
| }, | ||
| includeMeta: { type: 'boolean', default: false }, | ||
| orderByMostRecentFlows: { type: 'boolean', default: false } | ||
| } | ||
| } | ||
| ] | ||
| } | ||
| } | ||
| }, async (request, reply) => { | ||
| const includeMeta = request.query.includeMeta | ||
| const pagination = app.db.controllers.Project.getProjectPaginationOptions(request) | ||
|
|
||
| const options = { | ||
| includeSettings: true, | ||
| limit: request.query.limit, | ||
| pagination, | ||
| query: request.query.query?.trim() || null, | ||
| includeMeta, | ||
| orderByMostRecentFlows: request.query.orderByMostRecentFlows | ||
| } | ||
|
|
@@ -406,7 +408,10 @@ module.exports = async function (app) { | |
| } | ||
| } | ||
|
|
||
| const projects = await app.db.models.Project.byTeam(request.params.teamId, options) | ||
| const queryResult = await app.db.models.Project.byTeam(request.params.teamId, options) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is where we could send the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup refactored. |
||
| const paginated = pagination.page != null | ||
| const projects = paginated ? queryResult.rows : queryResult | ||
| const total = paginated ? queryResult.total : null | ||
|
|
||
| if (projects) { | ||
| let result = await app.db.views.Project.instancesList(projects, { | ||
|
|
@@ -420,10 +425,19 @@ module.exports = async function (app) { | |
| return { id: e.id, name: e.name } | ||
| }) | ||
| } | ||
| reply.send({ | ||
| count: result.length, | ||
| const response = { | ||
| count: paginated ? total : result.length, | ||
| projects: result | ||
| }) | ||
| } | ||
| if (paginated) { | ||
| response.meta = { | ||
| page: pagination.page, | ||
| pageSize: pagination.limit, | ||
| total, | ||
| pageCount: Math.max(1, Math.ceil(total / pagination.limit)) | ||
| } | ||
| } | ||
| reply.send(response) | ||
| } else { | ||
| reply.code(404).send({ code: 'not_found', error: 'Not Found' }) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -196,19 +196,39 @@ const getTeamInstancesList = async (teamId) => { | |
| } | ||
|
|
||
| const getInstances = async (teamId, { | ||
| limit = 20, | ||
| pagination = null, | ||
| includeMeta = false, | ||
| orderByMostRecentFlows = false | ||
| } = {}) => { | ||
| const { | ||
| page = null, | ||
| limit = 20, | ||
| query = null, | ||
| sort = null, | ||
| dir = null | ||
| } = pagination || {} | ||
| const params = new URLSearchParams() | ||
|
|
||
| params.append('limit', limit.toString()) | ||
|
|
||
| if (page !== null) params.append('page', String(page)) | ||
| if (query) params.append('query', query) | ||
| if (sort) params.append('sort', sort) | ||
| if (dir) params.append('dir', dir) | ||
| if (includeMeta) params.append('includeMeta', includeMeta.toString()) | ||
| if (orderByMostRecentFlows) params.append('orderByMostRecentFlows', orderByMostRecentFlows.toString()) | ||
|
|
||
| return await client.get(`/api/v1/teams/${teamId}/projects?${params.toString()}`) | ||
| .then(res => res.data) | ||
| const res = await client.get(`/api/v1/teams/${teamId}/projects?${params.toString()}`) | ||
| res.data.projects = res.data.projects.map(r => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what changed that we need to do this now, and we didn't before? nothing stood out for me
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So when I tested with a dashboard-only user I got a forever spinner. The old code path called The N+1 fix removed that fan-out, so dashboard rows (whose endpoint doesn't return meta) lost their |
||
| if (r.flowLastUpdatedAt) { | ||
| r.flowLastUpdatedSince = daysSince(r.flowLastUpdatedAt) | ||
| } | ||
| if (r.meta?.state) { | ||
| r.status = r.meta.state | ||
| } | ||
| return r | ||
| }) | ||
| return res.data | ||
| } | ||
|
|
||
| const getTeamMembers = (teamId) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pagination params already include sort as an option, was this only so we can type the endpoint more tightly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah
PaginationParams.sortis just a string, so unknown values would silently fall through to the default order. The enum makes the route 400 instead.