diff --git a/lib/components/user-identity-cache.react.js b/lib/components/user-identity-cache.react.js --- a/lib/components/user-identity-cache.react.js +++ b/lib/components/user-identity-cache.react.js @@ -8,16 +8,16 @@ UserIdentitiesResponse, Identity, } from '../types/identity-service-types.js'; +import { identityServiceQueryTimeout } from '../utils/identity-service.js'; import sleep from '../utils/sleep.js'; const cacheTimeout = 24 * 60 * 60 * 1000; // one day // If the query fails due to a timeout, we don't cache it // This forces a retry on the next request const failedQueryCacheTimeout = 0; -const queryTimeout = 20 * 1000; // twenty seconds async function throwOnTimeout(identifier: string) { - await sleep(queryTimeout); + await sleep(identityServiceQueryTimeout); throw new Error(`User identity fetch for ${identifier} timed out`); } @@ -189,7 +189,7 @@ })(); cache.set(userID, { userID, - expirationTime: Date.now() + queryTimeout * 2, + expirationTime: Date.now() + identityServiceQueryTimeout * 2, result: fetchUserIdentityPromise, }); } diff --git a/lib/handlers/user-infos-handler.react.js b/lib/handlers/user-infos-handler.react.js --- a/lib/handlers/user-infos-handler.react.js +++ b/lib/handlers/user-infos-handler.react.js @@ -168,7 +168,10 @@ usersWithMissingDeviceList, true, ); - Object.keys(foundDeviceListIDs).forEach(id => + const deviceListIDsToRemove = foundDeviceListIDs + ? Object.keys(foundDeviceListIDs) + : usersWithMissingDeviceList; + deviceListIDsToRemove.forEach(id => requestedDeviceListsIDsRef.current.delete(id), ); } catch (e) { diff --git a/lib/hooks/peer-list-hooks.js b/lib/hooks/peer-list-hooks.js --- a/lib/hooks/peer-list-hooks.js +++ b/lib/hooks/peer-list-hooks.js @@ -28,8 +28,10 @@ import { getConfig } from '../utils/config.js'; import { getContentSigningKey } from '../utils/crypto-utils.js'; import { convertSignedDeviceListsToRawDeviceLists } from '../utils/device-list-utils.js'; +import { identityServiceQueryTimeout } from '../utils/identity-service.js'; import { values } from '../utils/objects.js'; import { useDispatch, useSelector } from '../utils/redux-utils.js'; +import sleep from '../utils/sleep.js'; function useGetDeviceListsForUsers(): ( userIDs: $ReadOnlyArray, @@ -55,10 +57,15 @@ ); } +async function throwOnTimeout(userIDs: $ReadOnlyArray) { + await sleep(identityServiceQueryTimeout); + throw new Error(`Device list fetch for ${JSON.stringify(userIDs)} timed out`); +} + function useGetAndUpdateDeviceListsForUsers(): ( userIDs: $ReadOnlyArray, broadcastUpdates: ?boolean, -) => Promise { +) => Promise { const getDeviceListsForUsers = useGetDeviceListsForUsers(); const dispatch = useDispatch(); const broadcastDeviceListUpdates = useBroadcastDeviceListUpdates(); @@ -67,8 +74,21 @@ return React.useCallback( async (userIDs: $ReadOnlyArray, broadcastUpdates: ?boolean) => { - const { deviceLists, usersPlatformDetails } = - await getDeviceListsForUsers(userIDs); + let result; + try { + result = await Promise.race([ + getDeviceListsForUsers(userIDs), + throwOnTimeout(userIDs), + ]); + } catch (e) { + console.log(e); + } + + if (!result) { + return null; + } + + const { deviceLists, usersPlatformDetails } = result; if (Object.keys(deviceLists).length === 0) { return {}; } diff --git a/lib/shared/dm-ops/dm-op-utils.js b/lib/shared/dm-ops/dm-op-utils.js --- a/lib/shared/dm-ops/dm-op-utils.js +++ b/lib/shared/dm-ops/dm-op-utils.js @@ -172,6 +172,10 @@ true, ); + if (!deviceLists) { + return []; + } + const missingUsers: $ReadOnlyArray = missingDeviceListsUserIDs.filter(id => !deviceLists[id]); const time = Date.now(); diff --git a/lib/utils/identity-service.js b/lib/utils/identity-service.js --- a/lib/utils/identity-service.js +++ b/lib/utils/identity-service.js @@ -45,4 +45,6 @@ return `${identityServiceConfig.defaultHttpURL}${path}`; } -export { getInboundKeysForDeviceURL }; +const identityServiceQueryTimeout = 20 * 1000; // twenty seconds + +export { getInboundKeysForDeviceURL, identityServiceQueryTimeout };