Fix instance peering pagination (#15108)

Currently the association box displays a
list of available instances/addresses that can
be peered to.

The pagination issue arises as follows:

- fetch 5 instances (based on page_size)
- filter these instances down based on some
criteria (like is_internal: false)
- show results

Filtering down the results inside of the fetch
method results in pagnation errors (may return fewer than
5, for example)

instead, do the filtering by API queries. That way the
pagination count will be correct.

Signed-off-by: Seth Foster <fosterbseth@gmail.com>
This commit is contained in:
Seth Foster
2024-04-18 15:17:10 -04:00
committed by GitHub
parent c0f71801f6
commit f178c84728

View File

@@ -12,7 +12,7 @@ import AssociateModal from 'components/AssociateModal';
import ErrorDetail from 'components/ErrorDetail'; import ErrorDetail from 'components/ErrorDetail';
import AlertModal from 'components/AlertModal'; import AlertModal from 'components/AlertModal';
import useToast, { AlertVariant } from 'hooks/useToast'; import useToast, { AlertVariant } from 'hooks/useToast';
import { getQSConfig, parseQueryString, mergeParams } from 'util/qs'; import { getQSConfig, parseQueryString } from 'util/qs';
import { useLocation, useParams } from 'react-router-dom'; import { useLocation, useParams } from 'react-router-dom';
import useRequest, { useDismissableError } from 'hooks/useRequest'; import useRequest, { useDismissableError } from 'hooks/useRequest';
import DataListToolbar from 'components/DataListToolbar'; import DataListToolbar from 'components/DataListToolbar';
@@ -106,62 +106,38 @@ function InstancePeerList({ setBreadcrumb }) {
const { selected, isAllSelected, handleSelect, clearSelected, selectAll } = const { selected, isAllSelected, handleSelect, clearSelected, selectAll } =
useSelected(peers); useSelected(peers);
const fetchInstancesToAssociate = useCallback( const fetchPeersToAssociate = useCallback(
async (params) => { async (params) => {
const address_list = []; const address_list = [];
const instances = await InstancesAPI.read( // do not show this instance or instances that are already peered
mergeParams(params, { // to this instance (reverse_peers)
...{ not__node_type: ['control', 'hybrid'] }, const not_instances = instance.reverse_peers;
}) not_instances.push(instance.id);
);
const receptors = (await ReceptorAPI.read()).data.results;
// get instance ids of the current peered receptor ids params.not__instance = not_instances;
const already_peered_instance_ids = []; params.is_internal = false;
for (let h = 0; h < instance.peers.length; h++) { // do not show the current peers
const matched = receptors.filter((obj) => obj.id === instance.peers[h]); if (instance.peers.length > 0) {
matched.forEach((element) => { params.not__id__in = instance.peers.join(',');
already_peered_instance_ids.push(element.instance);
});
} }
for (let q = 0; q < receptors.length; q++) { const receptoraddresses = await ReceptorAPI.read(params);
const receptor = receptors[q];
if (already_peered_instance_ids.includes(receptor.instance)) { // retrieve the instances that are associated with those receptor addresses
// ignore reverse peers const instance_ids = receptoraddresses.data.results.map(
continue; (obj) => obj.instance
} );
const instance_ids_str = instance_ids.join(',');
const instances = await InstancesAPI.read({ id__in: instance_ids_str });
if (instance.peers.includes(receptor.id)) { for (let q = 0; q < receptoraddresses.data.results.length; q++) {
// no links to existing links const receptor = receptoraddresses.data.results[q];
continue;
}
if (instance.id === receptor.instance) {
// no links to thy self
continue;
}
if (instance.managed) {
// no managed nodes
continue;
}
const host = instances.data.results.filter( const host = instances.data.results.filter(
(obj) => obj.id === receptor.instance (obj) => obj.id === receptor.instance
)[0]; )[0];
if (host === undefined) {
// no hosts
continue;
}
if (receptor.is_internal) {
continue;
}
const copy = receptor; const copy = receptor;
copy.hostname = host.hostname; copy.hostname = host.hostname;
copy.node_type = host.node_type; copy.node_type = host.node_type;
@@ -169,9 +145,9 @@ function InstancePeerList({ setBreadcrumb }) {
address_list.push(copy); address_list.push(copy);
} }
instances.data.results = address_list; receptoraddresses.data.results = address_list;
return instances; return receptoraddresses;
}, },
[instance] [instance]
); );
@@ -191,7 +167,7 @@ function InstancePeerList({ setBreadcrumb }) {
fetchPeers(); fetchPeers();
addToast({ addToast({
id: instancesPeerToAssociate, id: instancesPeerToAssociate,
title: t`Please be sure to run the install bundle for the selected instance(s) again in order to see changes take effect.`, title: t`Please be sure to run the install bundle for ${instance.hostname} again in order to see changes take effect.`,
variant: AlertVariant.success, variant: AlertVariant.success,
hasTimeout: true, hasTimeout: true,
}); });
@@ -315,13 +291,13 @@ function InstancePeerList({ setBreadcrumb }) {
{isModalOpen && ( {isModalOpen && (
<AssociateModal <AssociateModal
header={t`Instances`} header={t`Instances`}
fetchRequest={fetchInstancesToAssociate} fetchRequest={fetchPeersToAssociate}
isModalOpen={isModalOpen} isModalOpen={isModalOpen}
onAssociate={handlePeerAssociate} onAssociate={handlePeerAssociate}
onClose={() => setIsModalOpen(false)} onClose={() => setIsModalOpen(false)}
title={t`Select Peer Addresses`} title={t`Select Peer Addresses`}
optionsRequest={readInstancesOptions} optionsRequest={readInstancesOptions}
displayKey="hostname" displayKey="address"
columns={[ columns={[
{ key: 'hostname', name: t`Name` }, { key: 'hostname', name: t`Name` },
{ key: 'address', name: t`Address` }, { key: 'address', name: t`Address` },