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]);
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 =
selected.length === inventories.length && selected.length > 0;

View File

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

View File

@ -1,50 +1,88 @@
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 [lastMessage, setLastMessage] = useState(null);
const [inventoriesToFetch, setInventoriesToFetch] = useState([]);
const throttledInventoriesToFetch = useThrottle(inventoriesToFetch, 5000);
const ws = useRef(null);
useEffect(() => {
setInventories(initialInventories);
}, [initialInventories]);
// const messageExample = {
// unified_job_id: 533,
// status: 'pending',
// 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;
const enqueueId = id => {
if (!inventoriesToFetch.includes(id)) {
setInventoriesToFetch(ids => ids.concat(id));
}
};
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];
const updatedProject = {
...inventory,
summary_fields: {
...inventory.summary_fields,
// last_job: {
// id: lastMessage.unified_job_id,
// status: lastMessage.status,
// finished: lastMessage.finished,
// },
},
};
setInventories([
...inventories.slice(0, index),
updatedProject,
...inventories.slice(index + 1),
]);
}, [lastMessage]); // eslint-disable-line react-hooks/exhaustive-deps
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) {
return;
}
if (!['pending', 'waiting', 'running'].includes(lastMessage.status)) {
enqueueId(lastMessage.inventory_id);
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(() => {
ws.current = new WebSocket(`wss://${window.location.host}/websocket/`);