-
Notifications
You must be signed in to change notification settings - Fork 249
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
feat(api): Subscription Reconnection #2074
feat(api): Subscription Reconnection #2074
Conversation
* feat(api): GraphQL API key auth mode * BREAKING CHANGE: GraphQL response errors now nullable
…r registers in Auth (aws-amplify#1851)
Co-authored-by: Elijah Quartey <Equartey@users.noreply.github.com>
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
e6bb82b
to
b786902
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.
Still reviewing details, but left a few comments for now, plus will DM with some offline comments that I think need to be addressed.
packages/amplify_core/lib/src/types/api/graphql/graphql_subscription_options.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/types/api/graphql/graphql_subscription_options.dart
Show resolved
Hide resolved
|
||
/// Confiuration options for GraphQL Subscriptions and their websockets. | ||
class GraphQLSubscriptionOptions { | ||
/// Configure the ping interval for AppSync polling for subscription connections. |
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.
question: Would it make sense to state the default here? I'm guessing customers will see these comments when seeing what options they can provide and when deciding to provide a value or not it helps to know what the default is.
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
@@ -52,11 +52,12 @@ class WebSocketSubscriptionStreamTransformer<T> | |||
|
|||
/// executes when start_ack message received | |||
final void Function()? onEstablished; | |||
final Set<String> _establishedRequests = {}; |
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.
question: Is the intention here to ensure onEstablished not called again for same sub when reconnect occurs? Seems like a fine design decision if so.
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.
Correct, was seeing some scenarios that it was firing more than once.
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.
Should probably be static, no? Otherwise, each set will only ever contain one object since an instance of this is created for each request.
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.
Or if it's just for this request, then a boolean will do
@@ -5,6 +5,8 @@ | |||
import FlutterMacOS | |||
import Foundation | |||
|
|||
import connectivity_plus_macos |
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.
when I run aft bs
I get similar file modifications in packages/api/amplify_api/example/macos/Flutter/GeneratedPluginRegistrant.swift
. Should that be added as well?
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.
Yeah, I noticed some extra generated files didn't committed. Will include them next push 👍
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
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.
Looking good! Some minor comments mostly
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/types/api/hub/api_subscription_hub_event.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
_hubEventsController?.add(SubscriptionHubEvent.failed()); | ||
|
||
if (_hasNetwork && | ||
_hasConnectionBroken && |
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.
Not sure we want to check _hasConnectionBroken here since that will only be true if _hasNetwork is false really.
Actually, in what situation would we get here with network and not already be retrying?
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 see what you're saying. _hasConnectionBroken indicates that a connection existed at one point, but was interrupted & a retry attempt hasn't been made yet. If it's false, then we've already tried to recover.
That being said, since the called out code lives in the onError handler I agree _hasConnectionBroken doesn't need to be checked. Network related interruptions are being handled else where. The goal here is to recover from errors.
Good catch.
@@ -203,12 +391,15 @@ class WebSocketConnection implements Closeable { | |||
|
|||
/// Times out the connection (usually if a keep alive has not been received in time). | |||
void _timeout(Duration timeoutDuration) { | |||
_timeoutTimer?.cancel(); |
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.
Is the timeout timer still running when we lose network? Should it be?
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.
Currently no, the timer gets canceled during network interruptions. I think this is how we want it, do you think otherwise?
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
…2119) * chore(api): Refactor http client & cancelable operation
6a40c9f
to
f2b8414
Compare
1fe8b50
to
2809cc6
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.
just left some comments about possible rebase errors here
packages/amplify_core/lib/src/category/amplify_api_category.dart
Outdated
Show resolved
Hide resolved
packages/amplify_core/lib/src/plugin/amplify_api_plugin_interface.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/amplify_authorization_rest_client.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/test/ws/web_socket_auth_utils_test.dart
Outdated
Show resolved
Hide resolved
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.
Getting closer! Liking the change in tests, nice job there. Generally would try to get rid of all the lint warnings and get tests passing so CI on PR is green and flutter analyze
from amplify_api dir has no warnings.
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
return MockWebSocketChannel(); | ||
} | ||
|
||
MockWebSocketConnection getWebSocketConnection() { |
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.
suggestion/question: Could this get moved to test util so you can use in dart_graphql_test.dart too?
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 moved some of the logic, but can't completely reuse this logic as each test is implemented slightly different.
packages/api/amplify_api/test/ws/web_socket_connection_test.dart
Outdated
Show resolved
Hide resolved
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.
Still gonna test again but left a few small comments.
@@ -85,6 +85,10 @@ class AmplifyHubImpl extends AmplifyHub { | |||
Future.wait<void>([ | |||
for (final stream in _availableStreams.values) stream.close(), | |||
]).ignore(); | |||
Future.wait<void>([ |
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.
Missed this from before, but what does this block do?
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.
No worries, this was just added. @dnys1 helped debug this one. It cleans up hub event subscriptions on cancel, an issue I was seeing in testing.
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.
cool, thanks for info. Might be worth a small comment here to explain.
packages/amplify_core/lib/src/plugin/amplify_api_plugin_interface.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/test/ws/web_socket_connection_test.dart
Outdated
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## feat/api-next #2074 +/- ##
=================================================
+ Coverage 39.23% 39.69% +0.45%
=================================================
Files 120 120
Lines 6915 7039 +124
=================================================
+ Hits 2713 2794 +81
- Misses 4202 4245 +43
Flags with carried forward coverage won't be shown. Click here to find out more.
|
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
packages/api/amplify_api/lib/src/graphql/ws/web_socket_connection.dart
Outdated
Show resolved
Hide resolved
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.
LGTM 🚀
WebSocketConnection getWebSocketConnection({String? apiName}) => | ||
MockWebSocketConnection(testApiKeyConfig, getTestAuthProviderRepo()); | ||
WebSocketConnection getWebSocketConnection({String? apiName}) { | ||
return mockWebSocketConnection; |
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.
Should it be the same for every test?
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.
Yeah, I believe this is okay given the tests implementations.
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.
🚢 🔥 , love it! nice work
Issue #, if available:
Description of changes:
Provides GraphQL subscription reconnection and associated quality of life additions.
-- Connected The network is connected and has active subscriptions.
-- Connecting - The network is disconnected and has active subscriptions. Triggers for initial connect and reconnect events.
-- PendingDisconnect - The network is connected, but has no active subscriptions.
-- Disconnected - The network has been disconnected and no active subscriptions.
-- Failed - The network could not be connected.
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.