diff --git a/lib/selectors/socket-selectors.js b/lib/selectors/socket-selectors.js --- a/lib/selectors/socket-selectors.js +++ b/lib/selectors/socket-selectors.js @@ -147,32 +147,20 @@ const hashResults: { [string]: boolean } = {}; for (const key in serverRequest.hashesToCheck) { const expectedHashValue = serverRequest.hashesToCheck[key]; - let hashValue; const [specKey, id] = key.split('|'); - if (id) { - hashValue = specPerInnerHashKey[specKey]?.getInfoHash( - id, - keyserverID, - ); - } else { - hashValue = specsPerHashKey[specKey]?.getAllInfosHash( - query, - keyserverID, - ); - } + const spec = id + ? specPerInnerHashKey[specKey] + : specsPerHashKey[specKey]; - // If hashValue values is null then we are still calculating - // the hashes in the background. In this case we return true - // to skip this state check. Future state checks (after the hash - // calculation complete) will be handled normally. - // Another case when this is null is when we are handling state - // sync with a non-authoritative keyserver. We don't want to sync - // user store and current user info with such keyservers. - if (!hashValue) { + if (!spec?.canSyncState(keyserverID)) { hashResults[key] = true; - } else { - hashResults[key] = expectedHashValue === hashValue; + continue; } + + const hashValue = id + ? spec?.getInfoHash(id, keyserverID) + : spec?.getAllInfosHash(query, keyserverID); + hashResults[key] = expectedHashValue === hashValue; } const { failUnmentioned } = serverRequest; diff --git a/lib/shared/state-sync/current-user-state-sync-spec.js b/lib/shared/state-sync/current-user-state-sync-spec.js --- a/lib/shared/state-sync/current-user-state-sync-spec.js +++ b/lib/shared/state-sync/current-user-state-sync-spec.js @@ -24,6 +24,8 @@ return hash(currentUserInfo); }, getIDs: () => ([]: string[]), + canSyncState: (keyserverID: string) => + keyserverID === authoritativeKeyserverID(), }), ); diff --git a/lib/shared/state-sync/entries-state-sync-spec.js b/lib/shared/state-sync/entries-state-sync-spec.js --- a/lib/shared/state-sync/entries-state-sync-spec.js +++ b/lib/shared/state-sync/entries-state-sync-spec.js @@ -42,6 +42,7 @@ getEntryInfosHash(entryInfos, calendarQuery, keyserverID), getIDs: (calendarQuery: CalendarQuery, keyserverID: string) => getEntryIDs(entryInfos, calendarQuery, keyserverID), + canSyncState: () => true, }), ); diff --git a/lib/shared/state-sync/state-sync-spec.js b/lib/shared/state-sync/state-sync-spec.js --- a/lib/shared/state-sync/state-sync-spec.js +++ b/lib/shared/state-sync/state-sync-spec.js @@ -24,12 +24,21 @@ // All ids specified here (getInfoHash and getIDs) are server ids. // E.g. in the case of threadStore or entryStore the keyserver prefix -// needs to be handled additionaly +// needs to be handled additionally export type BoundStateSyncSpec = { // If these function depend on background hashing that is still not complete // they should return null, to indicate that the hashes aren't available yet +getInfoHash: (id: string, keyserverID: string) => ?number, +getAllInfosHash: (query: CalendarQuery, keyserverID: string) => ?number, +getIDs: (query: CalendarQuery, keyserverID: string) => ?Array, + // This function is used to check if we can sync the state. + // Currently, there are two cases where we can't sync the state: + // 1. When background thread hashing is still in progress + // 2. When a non-authoritative keyserver attempts a state sync of UserStore + // or CurrentUserInfo + // If we can't do a state sync, we're informing a keyserver that all + // the hashes are correct. Later, the keyserver will attempt a state sync + // again. + +canSyncState: (keyserverID: string) => boolean, ...StateSyncSpec, }; diff --git a/lib/shared/state-sync/threads-state-sync-spec.js b/lib/shared/state-sync/threads-state-sync-spec.js --- a/lib/shared/state-sync/threads-state-sync-spec.js +++ b/lib/shared/state-sync/threads-state-sync-spec.js @@ -51,6 +51,7 @@ .filter(id => extractKeyserverIDFromID(id) === keyserverID) .map(id => id.split('|')[1]) : () => null, + canSyncState: () => threadHashingComplete, }), ); diff --git a/lib/shared/state-sync/users-state-sync-spec.js b/lib/shared/state-sync/users-state-sync-spec.js --- a/lib/shared/state-sync/users-state-sync-spec.js +++ b/lib/shared/state-sync/users-state-sync-spec.js @@ -42,6 +42,8 @@ } return Object.keys(userInfos); }, + canSyncState: (keyserverID: string) => + keyserverID === authoritativeKeyserverID(), }), );