fetch keys as part of afterSyncCompleted step

remove needsAfterSyncCompleted step as well, performance difference
should be neglible
This commit is contained in:
Bruno Windels 2022-10-28 16:25:31 +02:00
parent 9c13b2b4a4
commit fcb1546fba
3 changed files with 41 additions and 19 deletions

View File

@ -47,10 +47,8 @@ function timelineIsEmpty(roomResponse) {
* const changes = await room.writeSync(roomResponse, isInitialSync, preparation, syncTxn); * const changes = await room.writeSync(roomResponse, isInitialSync, preparation, syncTxn);
* // applies and emits changes once syncTxn is committed * // applies and emits changes once syncTxn is committed
* room.afterSync(changes); * room.afterSync(changes);
* if (room.needsAfterSyncCompleted(changes)) { * // can do network requests
* // can do network requests * await room.afterSyncCompleted(changes);
* await room.afterSyncCompleted(changes);
* }
* ``` * ```
*/ */
export class Sync { export class Sync {
@ -163,13 +161,9 @@ export class Sync {
await log.wrap("session", log => this._session.afterSyncCompleted(sessionChanges, isCatchupSync, log), log.level.Detail); await log.wrap("session", log => this._session.afterSyncCompleted(sessionChanges, isCatchupSync, log), log.level.Detail);
} catch (err) {} // error is logged, but don't fail sessionPromise } catch (err) {} // error is logged, but don't fail sessionPromise
})(); })();
const roomsPromises = roomStates.map(async rs => {
const roomsNeedingAfterSyncCompleted = roomStates.filter(rs => {
return rs.room.needsAfterSyncCompleted(rs.changes);
});
const roomsPromises = roomsNeedingAfterSyncCompleted.map(async rs => {
try { try {
await log.wrap("room", log => rs.room.afterSyncCompleted(rs.changes, log), log.level.Detail); await rs.room.afterSyncCompleted(rs.changes, log);
} catch (err) {} // error is logged, but don't fail roomsPromises } catch (err) {} // error is logged, but don't fail roomsPromises
}); });
// run everything in parallel, // run everything in parallel,

View File

@ -557,15 +557,17 @@ class BatchDecryptionResult {
this._roomEncryption = roomEncryption; this._roomEncryption = roomEncryption;
} }
applyToEntries(entries) { applyToEntries(entries, callback = undefined) {
for (const entry of entries) { for (const entry of entries) {
const result = this.results.get(entry.id); const result = this.results.get(entry.id);
if (result) { if (result) {
entry.setDecryptionResult(result); entry.setDecryptionResult(result);
callback?.(entry);
} else { } else {
const error = this.errors.get(entry.id); const error = this.errors.get(entry.id);
if (error) { if (error) {
entry.setDecryptionError(error); entry.setDecryptionError(error);
callback?.(entry);
} }
} }
} }
@ -577,6 +579,15 @@ class BatchDecryptionResult {
return this._roomEncryption._verifyDecryptionResults(Array.from(this.results.values()), txn); return this._roomEncryption._verifyDecryptionResults(Array.from(this.results.values()), txn);
} }
get hasUnverifiedSenders() {
for (const r of this.results.values()) {
if (r.isVerificationUnknown) {
return true;
}
}
return false;
}
/** Verify any decryption results for which we could not find a device when /** Verify any decryption results for which we could not find a device when
* calling `verifyKnownSenders` prior, by fetching them from the homeserver. * calling `verifyKnownSenders` prior, by fetching them from the homeserver.
* @returns {Promise<BatchDecryptionResult>} the results for which we found a device */ * @returns {Promise<BatchDecryptionResult>} the results for which we found a device */

View File

@ -189,6 +189,7 @@ export class Room extends BaseRoom {
heroChanges, heroChanges,
powerLevelsEvent, powerLevelsEvent,
encryptionChanges, encryptionChanges,
decryption
}; };
} }
@ -291,19 +292,35 @@ export class Room extends BaseRoom {
} }
} }
needsAfterSyncCompleted({encryptionChanges}) {
return encryptionChanges?.shouldFlush;
}
/** /**
* Only called if the result of writeSync had `needsAfterSyncCompleted` set. * Only called if the result of writeSync had `needsAfterSyncCompleted` set.
* Can be used to do longer running operations that resulted from the last sync, * Can be used to do longer running operations that resulted from the last sync,
* like network operations. * like network operations.
*/ */
async afterSyncCompleted(changes, log) { async afterSyncCompleted({encryptionChanges, decryption, newEntries, updatedEntries}, log) {
log.set("id", this.id); const shouldFlushKeys = encryptionChanges?.shouldFlush;
if (this._roomEncryption) { const shouldFetchUnverifiedSenders = this._isTimelineOpen && decryption?.hasUnverifiedSenders;
await this._roomEncryption.flushPendingRoomKeyShares(this._hsApi, null, log); // only log rooms where we actually do something
if (shouldFlushKeys || shouldFetchUnverifiedSenders) {
log.wrap({l: "room", id: this.id}, async log => {
const promises = [];
if (shouldFlushKeys) {
promises.push(this._roomEncryption.flushPendingRoomKeyShares(this._hsApi, null, log));
}
if (shouldFetchUnverifiedSenders) {
const promise = (async () => {
const newlyVerifiedDecryption = await decryption.fetchAndVerifyRemainingSenders(this._hsApi, log);
const verifiedEntries = [];
const updateCallback = entry => verifiedEntries.push(entry);
newlyVerifiedDecryption.applyToEntries(newEntries, updateCallback);
newlyVerifiedDecryption.applyToEntries(updated, updateCallback);
// TODO: update _observedEvents here as well?
this._timeline.replaceEntries(verifiedEntries);
});
promises.push(promise);
}
await Promise.all(promises);
});
} }
} }