Skip to content
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

Make ICipher.decrypt asynchronous #1293

Closed
lawrence-forooghian opened this issue May 24, 2023 · 4 comments
Closed

Make ICipher.decrypt asynchronous #1293

lawrence-forooghian opened this issue May 24, 2023 · 4 comments
Assignees

Comments

@lawrence-forooghian
Copy link
Collaborator

lawrence-forooghian commented May 24, 2023

The SubtleCrypto.decrypt method that we wish to start using in #1292 is an asynchronous-only API — it returns a Promise.

Our current internal cipher API (as described by the ICipher interface added in #1246) exposes a synchronous decrypt method. In light of the above, we will need to change this to an asynchronous method.

This will necessitate internal changes to the library but will also affect its public API, since the {Message, PresenceMessage}.{fromEncoded, fromEncodedArray} static methods, which are currently synchronous, may need to decrypt data and hence in light of the above may now need to perform an asynchronous operation.

We need to decide exactly how we'd like to change the public API — we will definitely need to have an asynchronous version of the aforementioned methods, but @owenpearson suggested that we might wish to also maintain synchronous variants (which, presumably, would fail in the case that the method needs to perform a decryption).

I've created #1302, in order to investigate the effort involved in the internal changes this change would require, so that we can then put an estimate on this issue.

@sync-by-unito
Copy link

sync-by-unito bot commented May 24, 2023

➤ Automation for Jira commented:

The link to the corresponding Jira issue is https://ably.atlassian.net/browse/SDK-3604

@lawrence-forooghian
Copy link
Collaborator Author

@owenpearson would you mind laying out your thoughts re continuing to provide a synchronous version of the {Message, PresenceMessage}.{fromEncoded, fromEncodedArray} public methods — how it might benefit users and whether you think it's worth it? I guess it depends on what we think are the common use cases of these methods, and whether we believe they're most likely usually being used in an asynchronous context anyway.

@lawrence-forooghian
Copy link
Collaborator Author

Spoke to @owenpearson today and he thinks we'll be fine to only offer an asynchronous version of {Message, PresenceMessage}.{fromEncoded, fromEncodedArray}.

lawrence-forooghian added a commit that referenced this issue May 30, 2023
In preparation for using SubtleCrypto.decrypt, which returns a promise.

Resolves #1293.
lawrence-forooghian added a commit that referenced this issue May 31, 2023
In preparation for using SubtleCrypto.decrypt, which returns a promise.

Resolves #1293.
lawrence-forooghian added a commit that referenced this issue May 31, 2023
In preparation for using SubtleCrypto.decrypt, which returns a promise.

Resolves #1293.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
As part of #1293 (making ICipher.decrypt asynchronous), we will be
making this method async, and another method will wish to wait on its
completion. As such, this should no longer be named as if it were only
an informative callback.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
This is preparation for #1293 (making ICipher.decrypt asynchronous).
This will require us to make RealtimeChannel#processMessage asynchronous.

Since RealtimeChannel#processMessage reads from and writes to the
_decodingContext.baseEncodedPreviousPayload property of the channel, we
need to ensure that, once this method becomes asynchronous, we serialise
access to this method — that is, we wait for one call to complete before
performing the next.

To do this, we need to introduce a queue. I decided to put this queue at
the level of the ConnectionManager instead of RealtimeChannel. This is
because ConnectionManager also has its own logic for deciding whether a
message should be processed — specifically, whether it comes from the
current transport — and I thought it made sense to evaluate these
conditions at the moment we pass the message to the channel. I’m not
100% sure this is the right choice, though, since it means that the
synchronisation is now the concern of three components
(ConnectionManager, Channels, RealtimeChannel) when it instead could be
the concern of just RealtimeChannel. But we can always revisit this.

The handling of the case where ConnectionManager#processChannelMessage
throws an error is copied from the places where this error was
previously handled — namely, WebSocketTransport.onWsData and
CometTransport.onData, both of which log an error message without
affecting the processing of subsequent messages.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
These are the tests that call RealtimeChannel#processMessage at their
top level. This is preparation for making that method asynchronous as
part of #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous). This is an
unavoidable public API change.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
In preparation for using (async-only) SubtleCrypto.decrypt.

Resolves #1293.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
This is preparation for #1293 (making ICipher.decrypt asynchronous).
This will require us to make RealtimeChannel#processMessage asynchronous.

Since RealtimeChannel#processMessage reads from and writes to the
_decodingContext.baseEncodedPreviousPayload property of the channel, we
need to ensure that, once this method becomes asynchronous, we serialise
access to this method — that is, we wait for one call to complete before
performing the next.

To do this, we need to introduce a queue. I decided to put this queue at
the level of the ConnectionManager instead of RealtimeChannel. This is
because ConnectionManager also has its own logic for deciding whether a
message should be processed — specifically, whether it comes from the
current transport — and I thought it made sense to evaluate these
conditions at the moment we pass the message to the channel. I’m not
100% sure this is the right choice, though, since it means that the
synchronisation is now the concern of three components
(ConnectionManager, Channels, RealtimeChannel) when it instead could be
the concern of just RealtimeChannel. But we can always revisit this.

The handling of the case where ConnectionManager#processChannelMessage
throws an error is copied from the places where this error was
previously handled — namely, WebSocketTransport.onWsData and
CometTransport.onData, both of which log an error message without
affecting the processing of subsequent messages.

(Note also that this marks the first use of `async` or promises
internally in the library. We have avoided this until now because we
were not guaranteed to be running in browsers with Promise support, but
since the library will _only_ be exposing a Promise API as of #1199,
which is also scheduled for version 2.0, we’re fine to start doing so
now.)
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
These are the tests that call RealtimeChannel#processMessage at their
top level. This is preparation for making that method asynchronous as
part of #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous). This is an
unavoidable public API change.

Note that I haven’t bothered exposing a callbacks version of these
methods, since as of #1199 — which is also scheduled for version 2.0 —
the library will only be exposing a Promise API.
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 1, 2023
In preparation for using the (async-only) SubtleCrypto.decrypt method
in #1292.

Resolves #1293.
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
As part of #1293 (making ICipher.decrypt asynchronous), we will be
making this method async, and another method will wish to wait on its
completion. As such, this should no longer be named as if it were only
an informative callback.
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
This is preparation for #1293 (making ICipher.decrypt asynchronous).
This will require us to make RealtimeChannel#processMessage asynchronous.

Since RealtimeChannel#processMessage reads from and writes to the
_decodingContext.baseEncodedPreviousPayload property of the channel, we
need to ensure that, once this method becomes asynchronous, we serialise
access to this method — that is, we wait for one call to complete before
performing the next.

To do this, we need to introduce a queue. I decided to put this queue at
the level of the ConnectionManager instead of RealtimeChannel. This is
because ConnectionManager also has its own logic for deciding whether a
message should be processed — specifically, whether it comes from the
current transport — and I thought it made sense to evaluate these
conditions at the moment we pass the message to the channel. I’m not
100% sure this is the right choice, though, since it means that the
synchronisation is now the concern of three components
(ConnectionManager, Channels, RealtimeChannel) when it instead could be
the concern of just RealtimeChannel. But we can always revisit this.

The handling of the case where ConnectionManager#processChannelMessage
throws an error is copied from the places where this error was
previously handled — namely, WebSocketTransport.onWsData and
CometTransport.onData, both of which log an error message without
affecting the processing of subsequent messages.

(Note also that this marks the first use of `async` or promises
internally in the library. We have avoided this until now because we
were not guaranteed to be running in browsers with Promise support, but
since the library will _only_ be exposing a Promise API as of #1199,
which is also scheduled for version 2.0, we’re fine to start doing so
now.)
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
These are the tests that call RealtimeChannel#processMessage at their
top level. This is preparation for making that method asynchronous as
part of #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous). This is an
unavoidable public API change.

Note that I haven’t bothered exposing a callbacks version of these
methods, since as of #1199 — which is also scheduled for version 2.0 —
the library will only be exposing a Promise API.
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
Preparation for #1293 (making ICipher.decrypt asynchronous).
lawrence-forooghian added a commit that referenced this issue Jun 5, 2023
In preparation for using the (async-only) SubtleCrypto.decrypt method
in #1292.

Resolves #1293.
@lawrence-forooghian
Copy link
Collaborator Author

Closed in #1311.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

1 participant