diff --git a/ts/session/apis/snode_api/swarmPolling.ts b/ts/session/apis/snode_api/swarmPolling.ts index 65529a3f7..25872d769 100644 --- a/ts/session/apis/snode_api/swarmPolling.ts +++ b/ts/session/apis/snode_api/swarmPolling.ts @@ -1,7 +1,17 @@ /* eslint-disable no-await-in-loop */ /* eslint-disable more/no-then */ /* eslint-disable @typescript-eslint/no-misused-promises */ -import { compact, concat, difference, flatten, last, sample, toNumber, uniqBy } from 'lodash'; +import { + compact, + concat, + difference, + flatten, + isEmpty, + last, + sample, + toNumber, + uniqBy, +} from 'lodash'; import { Data, Snode } from '../../../data/data'; import { SignalService } from '../../../protobuf'; import * as Receiver from '../../../receiver/receiver'; @@ -26,6 +36,7 @@ import { IncomingMessage } from '../../messages/incoming/IncomingMessage'; import { ed25519Str } from '../../onions/onionPath'; import { StringUtils, UserUtils } from '../../utils'; import { perfEnd, perfStart } from '../../utils/Performance'; +import { NotFoundError } from '../../utils/errors'; import { LibSessionUtil } from '../../utils/libsession/libsession_utils'; import { SnodeNamespace, SnodeNamespaces } from './namespaces'; import { SnodeAPIRetrieve } from './retrieveRequest'; @@ -349,7 +360,7 @@ export class SwarmPolling { private async handleSharedConfigMessages( userConfigMessagesMerged: Array, - returnAndKeepInMemory?: boolean + returnDisplayNameOnly?: boolean ): Promise { const extractedUserConfigMessage = compact( userConfigMessagesMerged.map((m: RetrieveMessageItem) => { @@ -396,7 +407,7 @@ export class SwarmPolling { `handleConfigMessagesViaLibSession of "${allDecryptedConfigMessages.length}" messages with libsession` ); - if (returnAndKeepInMemory) { + if (returnDisplayNameOnly) { let displayName = ''; try { @@ -421,14 +432,13 @@ export class SwarmPolling { ]); const userInfo = await UserConfigWrapperActions.getUserInfo(); - window.log.debug(`WIP: [SwarmPolling] userInfo: ${JSON.stringify(userInfo)}`); if (!userInfo) { throw new Error('UserInfo not found'); } displayName = userInfo.name; } catch (e) { window.log.warn( - '[SwarmPolling] LibSessionUtil.initializeLibSessionUtilWrappers failed with', + 'LibSessionUtil.initializeLibSessionUtilWrappers failed with', e.message ); } finally { @@ -653,77 +663,58 @@ export class SwarmPolling { // return the cached value return this.lastHashes[nodeEdKey][pubkey][namespace]; } - - /** - * Only exposed as public for testing - */ - public async pollOnceForDisplayName(pubkey: PubKey): Promise { - const polledPubkey = pubkey.key; - const swarmSnodes = await snodePool.getSwarmFor(polledPubkey); - - // Select nodes for which we already have lastHashes - const alreadyPolled = swarmSnodes.filter((n: Snode) => this.lastHashes[n.pubkey_ed25519]); - let toPollFrom = alreadyPolled.length ? alreadyPolled[0] : null; - - // If we need more nodes, select randomly from the remaining nodes: - if (!toPollFrom) { - const notPolled = difference(swarmSnodes, alreadyPolled); - toPollFrom = sample(notPolled) as Snode; - } - - let resultsFromUserProfile: RetrieveMessagesResultsBatched | null; - + public async pollOnceForOurDisplayName(): Promise { try { - resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName( - toPollFrom, - UserUtils.getOurPubKeyStrFromCache() - ); - } catch (e) { - if (e.message === ERROR_CODE_NO_CONNECT) { - if (window.inboxStore?.getState().onionPaths.isOnline) { - window.inboxStore?.dispatch(updateIsOnline(false)); - } - } else if (!window.inboxStore?.getState().onionPaths.isOnline) { - window.inboxStore?.dispatch(updateIsOnline(true)); + const pubkey = UserUtils.getOurPubKeyFromCache(); + const polledPubkey = pubkey.key; + const swarmSnodes = await snodePool.getSwarmFor(polledPubkey); + + // Select nodes for which we already have lastHashes + const alreadyPolled = swarmSnodes.filter((n: Snode) => this.lastHashes[n.pubkey_ed25519]); + let toPollFrom = alreadyPolled.length ? alreadyPolled[0] : null; + + // If we need more nodes, select randomly from the remaining nodes: + if (!toPollFrom) { + const notPolled = difference(swarmSnodes, alreadyPolled); + toPollFrom = sample(notPolled) as Snode; } - window.log.warn( - `pollOnceForDisplayName of ${pubkey} namespace: SnodeNamespaces.UserProfile failed with: ${e.message}` + const resultsFromUserProfile = await SnodeAPIRetrieve.retrieveDisplayName( + toPollFrom, + pubkey.key ); - resultsFromUserProfile = null; - } - // check if we just fetched the details from the config namespaces. - // If yes, merge them together and exclude them from the rest of the messages. - if (resultsFromUserProfile?.length) { + // check if we just fetched the details from the config namespaces. + // If yes, merge them together and exclude them from the rest of the messages. + if (!resultsFromUserProfile?.length) { + throw new Error('resultsFromUserProfile is empty'); + } + const userConfigMessages = resultsFromUserProfile .filter(m => SnodeNamespace.isUserConfigNamespace(m.namespace)) .map(r => r.messages.messages); const userConfigMessagesMerged = flatten(compact(userConfigMessages)); - - if (userConfigMessagesMerged.length) { - const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true); - return displayName; + if (!userConfigMessagesMerged.length) { + throw new Error('after merging there are no user config messages'); } - } - return ''; - } + const displayName = await this.handleSharedConfigMessages(userConfigMessagesMerged, true); - public async pollForOurDisplayName(): Promise { - if (!window.getGlobalOnlineStatus()) { - window?.log?.error('pollForOurDisplayName: offline'); - // Very important to set up a new polling call so we do retry at some point - setTimeout(this.pollForOurDisplayName.bind(this), SWARM_POLLING_TIMEOUT.ACTIVE); - return ''; - } + if (isEmpty(displayName)) { + throw new NotFoundError('Got a config message from network but without a displayName...'); + } - try { - const displayName = await this.pollOnceForDisplayName(UserUtils.getOurPubKeyFromCache()); - window.log.debug(`WIP: [pollForOurDisplayName] displayName ${displayName}`); + window.log.debug(`WIP: [pollOnceForOurDisplayName] displayName ${displayName}`); return displayName; } catch (e) { - window?.log?.warn('pollForOurDisplayName exception: ', e); + if (e.message === ERROR_CODE_NO_CONNECT) { + if (window.inboxStore?.getState().onionPaths.isOnline) { + window.inboxStore?.dispatch(updateIsOnline(false)); + } + } else if (!window.inboxStore?.getState().onionPaths.isOnline) { + window.inboxStore?.dispatch(updateIsOnline(true)); + } + window.log.debug(`WIP: [pollOnceForOurDisplayName] no displayName found`, e); throw e; } } diff --git a/ts/util/accountManager.ts b/ts/util/accountManager.ts index 162fe1b33..51c0458d6 100644 --- a/ts/util/accountManager.ts +++ b/ts/util/accountManager.ts @@ -84,7 +84,7 @@ export async function signInByLinkingDevice( await saveRecoveryPhrase(mnemonic); const pubKeyString = toHex(identityKeyPair.pubKey); - const displayName = await getSwarmPollingInstance().pollForOurDisplayName(); + const displayName = await getSwarmPollingInstance().pollOnceForOurDisplayName(); if (isEmpty(pubKeyString)) { throw new Error("We don't have a pubkey from the recovery password...");