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, useEffect(
// group_name: 'jobs', function fetchUpdatedInventories() {
// unified_job_template_id: 53, (async () => {
// }; if (!throttledInventoriesToFetch.length) {
useEffect(() => {
if (!lastMessage?.unified_job_id || lastMessage.type !== 'project_update') {
return; return;
} }
const index = inventories.findIndex(p => p.id === lastMessage.project_id); 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]
);
useEffect(
function processWsMessage() {
if (
!lastMessage?.inventory_id ||
lastMessage.type !== 'inventory_update'
) {
return;
}
const index = inventories.findIndex(
p => p.id === lastMessage.inventory_id
);
if (index === -1) { if (index === -1) {
return; return;
} }
if (!['pending', 'waiting', 'running'].includes(lastMessage.status)) {
enqueueId(lastMessage.inventory_id);
return;
}
const inventory = inventories[index]; const inventory = inventories[index];
const updatedProject = { const updatedInventory = {
...inventory, ...inventory,
summary_fields: { isSourceSyncRunning: true,
...inventory.summary_fields,
// last_job: {
// id: lastMessage.unified_job_id,
// status: lastMessage.status,
// finished: lastMessage.finished,
// },
},
}; };
setInventories([ setInventories([
...inventories.slice(0, index), ...inventories.slice(0, index),
updatedProject, updatedInventory,
...inventories.slice(index + 1), ...inventories.slice(index + 1),
]); ]);
}, [lastMessage]); // eslint-disable-line react-hooks/exhaustive-deps },
// 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/`);