-
-
Notifications
You must be signed in to change notification settings - Fork 590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reduce Megolm blocking and add cancellation #3035
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes look pretty straightforward, thanks.
For the record, you're actually free to use setImmediate
here, since any time the js-sdk gets used in a browser, it invariably gets run through Babel which has polyfills for that.
src/crypto/algorithms/megolm.ts
Outdated
*/ | ||
public prepareToEncrypt(room: Room): void { | ||
public prepareToEncrypt(room: Room): Stop { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer to just write out () => void
instead of Stop
, since the doc comments already describe well enough what the return value does, and when the types are this simple, aliases tend to only add confusion.
src/crypto/algorithms/megolm.ts
Outdated
// Yield prior to checking each device so that we don't block | ||
// updating/rendering for too long. | ||
// See https://github.com/vector-im/element-web/issues/21612 | ||
await sleep(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I see how this would unblock the event loop and fix the linked issue, I also want to make sure this won't create a performance regression in encryptMessage
. It's quite possible that there will be a lot of devices processed here, and the HTML spec claims that after 5 nested calls, any further setTimeout
calls are clamped to a minimum delay, which could add up.
Perhaps it would be more appropriate for the function to only yield on cancelable operations?
await sleep(0); | |
if (isCancelled !== undefined) await sleep(0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I'd never heard about the minimum delay!
Swapping to setImmediate
, since it's polyfilled, which should obviate the problem. Seems core-js
provides a MessageChannel
-based implementation, only falling back to setTimeout
on browsers that aren't targeted.
Also added the conditional!
Adds an async/promise-based version of `setImmediate`. Note that, despite being poorly adopted, `setImmediate` is polyfilled, and should be more performant than `sleep(0)`. Signed-off-by: Clark Fischer <clark.fischer@gmail.com>
Currently, calling `Client#prepareToEncrypt` in a megolm room has the potential to block for multiple seconds while it crunches numbers. Sleeping for 0 seconds (approximating `setImmediate`) allows the engine to process other events, updates, or re-renders in between checks. See - element-hq/element-web#21612 - element-hq/element-web#11836 Signed-off-by: Clark Fischer <clark.fischer@gmail.com>
NOTE: This commit introduces a backwards-compatible API change. Adds the ability to cancel `MegolmEncryption#prepareToEncrypt` by returning a cancellation function. The bulk of the processing happens in `getDevicesInRoom`, which now accepts a 'getter' that allows the caller to indicate cancellation. See matrix-org#1255 Closes matrix-org#1255 Signed-off-by: Clark Fischer <clark.fischer@gmail.com>
7fb2b39
to
1ee487a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the wait, this looks good to land now 👍
* Element-R: implement encryption of outgoing events ([\matrix-org#3122](matrix-org#3122)). * Poll model - page /relations results ([\matrix-org#3073](matrix-org#3073)). Contributed by @kerryarchibald. * Poll model - validate end events ([\matrix-org#3072](matrix-org#3072)). Contributed by @kerryarchibald. * Handle optional last_known_event_id property in m.predecessor ([\matrix-org#3119](matrix-org#3119)). Contributed by @andybalaam. * Add support for stable identifier for fixed MAC in SAS verification ([\matrix-org#3101](matrix-org#3101)). * Provide eventId as well as roomId from Room.findPredecessor ([\matrix-org#3095](matrix-org#3095)). Contributed by @andybalaam. * MSC3946 Dynamic room predecessors ([\matrix-org#3042](matrix-org#3042)). Contributed by @andybalaam. * Poll model ([\matrix-org#3036](matrix-org#3036)). Contributed by @kerryarchibald. * Remove video tracks on video mute without renegotiating ([\matrix-org#3091](matrix-org#3091)). * Introduces a backwards-compatible API change. `MegolmEncrypter#prepareToEncrypt`'s return type has changed from `void` to `() => void`. ([\matrix-org#3035](matrix-org#3035)). Contributed by @clarkf. * Stop the ICE disconnected timer on call terminate ([\matrix-org#3147](matrix-org#3147)). * Clear notifications when we can infer read status from receipts ([\matrix-org#3139](matrix-org#3139)). Fixes element-hq/element-web#23991. * Messages sent out of order after one message fails ([\matrix-org#3131](matrix-org#3131)). Fixes element-hq/element-web#22885 and element-hq/element-web#18942. Contributed by @justjanne. * Element-R: fix a bug which prevented encryption working after a reload ([\matrix-org#3126](matrix-org#3126)). * Element-R: Fix invite processing ([\matrix-org#3121](matrix-org#3121)). * Don't throw with no `opponentDeviceInfo` ([\matrix-org#3107](matrix-org#3107)). * Remove flaky megolm test ([\matrix-org#3098](matrix-org#3098)). Contributed by @clarkf. * Fix "verifyLinks" functionality of getRoomUpgradeHistory ([\matrix-org#3089](matrix-org#3089)). Contributed by @andybalaam.
This was originally intended to help with element-hq/element-web#21612, but ended up addressing #1255 as well.
The input delay was addressed by adding a
setTimeout
to the cpu-bound portion of the code. That should allow rendering code and event handlers to preempt key preparation periodically. Should help somewhat, but probably not a full solution. Ideally,setImmediate
should be used or approximated, but it's basically not supported in any browser, so 0ms timeouts it is.That allowed for cancellation to be addressed. There are multiple ways this could have been achieved, and I wasn't able to find a clear precedent. I opted for passing around stateful closures. It had the most minimal impact on the API that I could come up with.
I've tried my best to follow the contribution guidelines and code style documentation, but this is my first (substantial) contribution. Any and all feedback welcome!
Checklist
Notes: Introduces a backwards-compatible API change.
MegolmEncrypter#prepareToEncrypt
's return type has changed fromvoid
to() => void
.Here's what your changelog entry will look like:
✨ Features
MegolmEncrypter#prepareToEncrypt
's return type has changed fromvoid
to() => void
. (#3035). Contributed by @clarkf.