@@ -23,36 +23,40 @@ mixin RealtimeMixin {
23
23
int? get closeCode => _websok?.closeCode;
24
24
Map<int , RealtimeSubscription > _subscriptions = {};
25
25
bool _notifyDone = true;
26
+ bool _reconnect = true;
27
+ int _retries = 0;
26
28
StreamSubscription? _websocketSubscription;
27
29
bool _creatingSocket = false;
28
30
29
31
Future<dynamic > _closeConnection() async {
30
32
await _websocketSubscription?.cancel();
31
33
await _websok?.sink.close(status.normalClosure, 'Ending session');
32
34
_lastUrl = null;
35
+ _retries = 0;
36
+ _reconnect = false;
33
37
}
34
38
35
39
_createSocket() async {
36
40
if(_creatingSocket || _channels.isEmpty) return;
37
41
_creatingSocket = true;
38
42
final uri = _prepareUri();
39
- if (_websok == null) {
40
- _websok = await getWebSocket(uri);
41
- _lastUrl = uri.toString();
42
- } else {
43
- if (_lastUrl == uri.toString() && _websok?.closeCode == null) {
44
- _creatingSocket = false;
45
- return;
46
- }
47
- _notifyDone = false;
48
- await _closeConnection();
49
- _lastUrl = uri.toString();
50
- _websok = await getWebSocket(uri);
51
- _notifyDone = true;
52
- }
53
- debugPrint('subscription: $_lastUrl');
54
-
55
43
try {
44
+ if (_websok == null || _websok?.closeCode != null) {
45
+ _websok = await getWebSocket(uri);
46
+ _lastUrl = uri.toString();
47
+ } else {
48
+ if (_lastUrl == uri.toString() && _websok?.closeCode == null) {
49
+ _creatingSocket = false;
50
+ return;
51
+ }
52
+ _notifyDone = false;
53
+ await _closeConnection();
54
+ _lastUrl = uri.toString();
55
+ _websok = await getWebSocket(uri);
56
+ _notifyDone = true;
57
+ }
58
+ debugPrint('subscription: $_lastUrl');
59
+ _retries = 0;
56
60
_websocketSubscription = _websok?.stream.listen((response) {
57
61
final data = RealtimeResponse.fromJson(response);
58
62
switch (data.type) {
@@ -87,34 +91,44 @@ mixin RealtimeMixin {
87
91
break;
88
92
}
89
93
}, onDone: () {
90
- final subscriptions = List.from(_subscriptions.values);
91
- for (var subscription in subscriptions) {
92
- subscription.close();
93
- }
94
- _channels.clear();
95
- _closeConnection();
94
+ _retry();
96
95
}, onError: (err, stack) {
97
96
for (var subscription in _subscriptions.values) {
98
97
subscription.controller.addError(err, stack);
99
98
}
100
- if (_websok?.closeCode != null && _websok?.closeCode != 1008) {
101
- debugPrint("Reconnecting in one second.");
102
- Future.delayed(Duration(seconds: 1), _createSocket);
103
- }
99
+ _retry();
104
100
});
105
101
} catch (e) {
106
102
if (e is {{spec .title | caseUcfirst }}Exception) {
107
103
rethrow;
108
104
}
109
- if (e is WebSocketChannelException) {
110
- throw {{spec .title | caseUcfirst }}Exception(e.message);
111
- }
112
- throw {{spec .title | caseUcfirst }}Exception(e.toString());
105
+ debugPrint(e.toString());
106
+ _retry();
113
107
} finally {
114
108
_creatingSocket = false;
115
109
}
116
110
}
117
111
112
+ void _retry() async {
113
+ if (!_reconnect || _websok?.closeCode == status.policyViolation) {
114
+ _reconnect = true;
115
+ return;
116
+ }
117
+ _retries++;
118
+ debugPrint("Reconnecting in ${_getTimeout()} seconds.");
119
+ Future.delayed(Duration(seconds: _getTimeout()), _createSocket);
120
+ }
121
+
122
+ int _getTimeout() {
123
+ return _retries < 5
124
+ ? 1
125
+ : _retries < 15
126
+ ? 5
127
+ : _retries < 100
128
+ ? 10
129
+ : 60;
130
+ }
131
+
118
132
Uri _prepareUri() {
119
133
if (client.endPointRealtime == null) {
120
134
throw {{spec .title | caseUcfirst }}Exception(
@@ -167,13 +181,10 @@ mixin RealtimeMixin {
167
181
}
168
182
169
183
void handleError(RealtimeResponse response) {
170
- if (response.data['code'] == 1008 ) {
171
- throw AppwriteException (response.data["message"], response.data["code"]);
184
+ if (response.data['code'] == status.policyViolation ) {
185
+ throw {{ spec . title | caseUcfirst }}Exception (response.data["message"], response.data["code"]);
172
186
} else {
173
- debugPrint("Reconnecting in one second.");
174
- Future.delayed(const Duration(seconds: 1), () {
175
- _createSocket();
176
- });
187
+ _retry();
177
188
}
178
189
}
179
190
}
0 commit comments