diff --git a/lib/components/integrity-handler.react.js b/lib/components/integrity-handler.react.js index 093e2bd9f..2048492df 100644 --- a/lib/components/integrity-handler.react.js +++ b/lib/components/integrity-handler.react.js @@ -1,63 +1,74 @@ // @flow import * as React from 'react'; import { updateIntegrityStoreActionType } from '../actions/integrity-actions.js'; import { splitIntoChunks } from '../utils/array.js'; import { useSelector, useDispatch } from '../utils/redux-utils.js'; const BATCH_SIZE = 50; // Time between hashing of each thread batch const BATCH_INTERVAL = 500; // in milliseconds function IntegrityHandler(): null { const dispatch = useDispatch(); const threadInfos = useSelector(state => state.threadStore.threadInfos); const integrityStore = useSelector(state => state.integrityStore); const [batches, setBatches] = React.useState>>(null); const timeout = React.useRef(null); React.useEffect(() => { if (integrityStore.threadHashingStatus === 'starting') { - const threadIDs = Object.keys(threadInfos); + const integrityStoreThreads = new Set( + Object.keys(integrityStore.threadHashes), + ); + + const threadIDs = Object.keys(threadInfos).filter( + key => !integrityStoreThreads.has(key), + ); setBatches(splitIntoChunks(threadIDs, BATCH_SIZE)); dispatch({ type: updateIntegrityStoreActionType, payload: { threadHashingStatus: 'running' }, }); } else if (integrityStore.threadHashingStatus === 'completed') { clearTimeout(timeout.current); setBatches(null); } - }, [dispatch, integrityStore.threadHashingStatus, threadInfos]); + }, [ + dispatch, + integrityStore.threadHashes, + integrityStore.threadHashingStatus, + threadInfos, + ]); React.useEffect(() => { if (!batches) { return undefined; } const [batch, ...rest] = batches; if (!batch) { dispatch({ type: updateIntegrityStoreActionType, payload: { threadHashingStatus: 'completed' }, }); return undefined; } dispatch({ type: updateIntegrityStoreActionType, payload: { threadIDsToHash: batch }, }); const timeoutID = setTimeout(() => setBatches(rest), BATCH_INTERVAL); timeout.current = timeoutID; return () => clearTimeout(timeoutID); }, [batches, dispatch]); return null; } export default IntegrityHandler; diff --git a/lib/reducers/integrity-reducer.js b/lib/reducers/integrity-reducer.js index 42a47fe63..257eadd7e 100644 --- a/lib/reducers/integrity-reducer.js +++ b/lib/reducers/integrity-reducer.js @@ -1,85 +1,88 @@ // @flow import { setClientDBStoreActionType } from '../actions/client-db-store-actions.js'; import { updateIntegrityStoreActionType } from '../actions/integrity-actions.js'; import { siweAuthActionTypes } from '../actions/siwe-actions.js'; import { + keyserverAuthActionTypes, logInActionTypes, registerActionTypes, } from '../actions/user-actions.js'; import type { ThreadStoreOperation } from '../ops/thread-store-ops'; import type { IntegrityStore } from '../types/integrity-types'; import type { BaseAction } from '../types/redux-types.js'; import { fullStateSyncActionType } from '../types/socket-types.js'; import type { RawThreadInfo } from '../types/thread-types.js'; import { hash } from '../utils/objects.js'; function reduceIntegrityStore( state: IntegrityStore, action: BaseAction, threadInfos: { +[string]: RawThreadInfo }, threadStoreOperations: $ReadOnlyArray, ): IntegrityStore { if ( action.type === logInActionTypes.success || action.type === siweAuthActionTypes.success || action.type === registerActionTypes.success || action.type === fullStateSyncActionType || (action.type === setClientDBStoreActionType && !!action.payload.threadStore && state.threadHashingStatus !== 'completed') ) { return { threadHashes: {}, threadHashingStatus: 'starting' }; + } else if (action.type === keyserverAuthActionTypes.success) { + return { ...state, threadHashingStatus: 'starting' }; } let newState = state; if (action.type === updateIntegrityStoreActionType) { if (action.payload.threadIDsToHash) { const newThreadHashes = Object.fromEntries( action.payload.threadIDsToHash .map(id => [id, threadInfos[id]]) .filter(([, info]) => !!info) .map(([id, info]) => [id, hash(info)]), ); newState = { ...newState, threadHashes: { ...newState.threadHashes, ...newThreadHashes, }, }; } if (action.payload.threadHashingStatus) { newState = { ...newState, threadHashingStatus: action.payload.threadHashingStatus, }; } } if (threadStoreOperations.length === 0) { return newState; } let processedThreadHashes = { ...newState.threadHashes }; let threadHashingStatus = newState.threadHashingStatus; for (const operation of threadStoreOperations) { if (operation.type === 'replace') { processedThreadHashes[operation.payload.id] = hash( operation.payload.threadInfo, ); } else if (operation.type === 'remove') { for (const id of operation.payload.ids) { delete processedThreadHashes[id]; } } else if (operation.type === 'remove_all') { processedThreadHashes = {}; threadHashingStatus = 'completed'; } } return { ...newState, threadHashes: processedThreadHashes, threadHashingStatus, }; } export { reduceIntegrityStore };