websockets: show live inventory source sync status

This commit is contained in:
Keith Grant
2020-07-08 15:20:42 -07:00
parent 15ae0976dd
commit 84bea3d348
3 changed files with 86 additions and 37 deletions

View File

@@ -57,7 +57,16 @@ function InventoryList({ i18n }) {
fetchInventories(); fetchInventories();
}, [fetchInventories]); }, [fetchInventories]);
const inventories = useWsInventories(results); const fetchInventoriesById = useCallback(
async ids => {
const params = parseQueryString(QS_CONFIG, location.search);
params.id__in = ids.join(',');
const { data } = await InventoriesAPI.read(params);
return data.results;
},
[location.search] // eslint-disable-line react-hooks/exhaustive-deps
);
const inventories = useWsInventories(results, fetchInventoriesById);
const isAllSelected = const isAllSelected =
selected.length === inventories.length && selected.length > 0; selected.length === inventories.length && selected.length > 0;

View File

@@ -54,7 +54,9 @@ function InventoryListItem({
const labelId = `check-action-${inventory.id}`; const labelId = `check-action-${inventory.id}`;
let syncStatus = 'disabled'; let syncStatus = 'disabled';
if (inventory.has_inventory_sources) { if (inventory.isSourceSyncRunning) {
syncStatus = 'syncing';
} else if (inventory.has_inventory_sources) {
syncStatus = syncStatus =
inventory.inventory_sources_with_failures > 0 ? 'error' : 'success'; inventory.inventory_sources_with_failures > 0 ? 'error' : 'success';
} }

View File

@@ -1,50 +1,88 @@
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import useThrottle from '../../../util/useThrottle';
export default function useWsProjects(initialInventories) { export default function useWsProjects(
initialInventories,
fetchInventoriesById
) {
const [inventories, setInventories] = useState(initialInventories); const [inventories, setInventories] = useState(initialInventories);
const [lastMessage, setLastMessage] = useState(null); const [lastMessage, setLastMessage] = useState(null);
const [inventoriesToFetch, setInventoriesToFetch] = useState([]);
const throttledInventoriesToFetch = useThrottle(inventoriesToFetch, 5000);
const ws = useRef(null); const ws = useRef(null);
useEffect(() => { useEffect(() => {
setInventories(initialInventories); setInventories(initialInventories);
}, [initialInventories]); }, [initialInventories]);
// const messageExample = { const enqueueId = id => {
// unified_job_id: 533, if (!inventoriesToFetch.includes(id)) {
// status: 'pending', setInventoriesToFetch(ids => ids.concat(id));
// type: 'inventory_update',
// inventory_source_id: 53,
// inventory_id: 5,
// group_name: 'jobs',
// unified_job_template_id: 53,
// };
useEffect(() => {
if (!lastMessage?.unified_job_id || lastMessage.type !== 'project_update') {
return;
}
const index = inventories.findIndex(p => p.id === lastMessage.project_id);
if (index === -1) {
return;
} }
};
useEffect(
function fetchUpdatedInventories() {
(async () => {
if (!throttledInventoriesToFetch.length) {
return;
}
setInventoriesToFetch([]);
const newInventories = await fetchInventoriesById(
throttledInventoriesToFetch
);
let updated = inventories;
newInventories.forEach(inventory => {
const index = inventories.findIndex(i => i.id === inventory.id);
if (index === -1) {
return;
}
updated = [
...updated.slice(0, index),
inventory,
...updated.slice(index + 1),
];
});
setInventories(updated);
})();
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[throttledInventoriesToFetch, fetchInventoriesById]
);
const inventory = inventories[index]; useEffect(
const updatedProject = { function processWsMessage() {
...inventory, if (
summary_fields: { !lastMessage?.inventory_id ||
...inventory.summary_fields, lastMessage.type !== 'inventory_update'
// last_job: { ) {
// id: lastMessage.unified_job_id, return;
// status: lastMessage.status, }
// finished: lastMessage.finished, const index = inventories.findIndex(
// }, p => p.id === lastMessage.inventory_id
}, );
}; if (index === -1) {
setInventories([ return;
...inventories.slice(0, index), }
updatedProject,
...inventories.slice(index + 1), if (!['pending', 'waiting', 'running'].includes(lastMessage.status)) {
]); enqueueId(lastMessage.inventory_id);
}, [lastMessage]); // eslint-disable-line react-hooks/exhaustive-deps return;
}
const inventory = inventories[index];
const updatedInventory = {
...inventory,
isSourceSyncRunning: true,
};
setInventories([
...inventories.slice(0, index),
updatedInventory,
...inventories.slice(index + 1),
]);
},
// eslint-disable-next-line react-hooks/exhaustive-deps,
[lastMessage]
);
useEffect(() => { useEffect(() => {
ws.current = new WebSocket(`wss://${window.location.host}/websocket/`); ws.current = new WebSocket(`wss://${window.location.host}/websocket/`);