@aws-amplify/pubsub 4.4.9 → 4.4.10-next.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -0
- package/dist/aws-amplify-pubsub.js +713 -378
- package/dist/aws-amplify-pubsub.js.map +1 -1
- package/dist/aws-amplify-pubsub.min.js +3 -3
- package/dist/aws-amplify-pubsub.min.js.map +1 -1
- package/lib/Providers/AWSAppSyncRealTimeProvider/index.d.ts +10 -2
- package/lib/Providers/AWSAppSyncRealTimeProvider/index.js +133 -90
- package/lib/Providers/AWSAppSyncRealTimeProvider/index.js.map +1 -1
- package/lib/Providers/MqttOverWSProvider.d.ts +5 -1
- package/lib/Providers/MqttOverWSProvider.js +152 -87
- package/lib/Providers/MqttOverWSProvider.js.map +1 -1
- package/lib/Providers/PubSubProvider.d.ts +1 -1
- package/lib/Providers/{AWSAppSyncRealTimeProvider/constants.d.ts → constants.d.ts} +9 -0
- package/lib/Providers/{AWSAppSyncRealTimeProvider/constants.js → constants.js} +9 -0
- package/lib/Providers/constants.js.map +1 -0
- package/lib/index.d.ts +3 -10
- package/lib/index.js +3 -10
- package/lib/index.js.map +1 -1
- package/lib/types/Provider.d.ts +10 -1
- package/lib/types/PubSub.d.ts +22 -8
- package/lib/types/PubSub.js +56 -0
- package/lib/types/PubSub.js.map +1 -1
- package/lib/types/index.d.ts +0 -17
- package/lib/types/index.js +4 -36
- package/lib/types/index.js.map +1 -1
- package/lib/utils/ConnectionStateMonitor.d.ts +2 -1
- package/lib/utils/ConnectionStateMonitor.js +21 -13
- package/lib/utils/ConnectionStateMonitor.js.map +1 -1
- package/lib/utils/ReachabilityMonitor/index.d.ts +3 -0
- package/lib/utils/ReachabilityMonitor/index.js +5 -0
- package/lib/utils/ReachabilityMonitor/index.js.map +1 -0
- package/lib/utils/ReachabilityMonitor/index.native.d.ts +3 -0
- package/lib/utils/ReachabilityMonitor/index.native.js +11 -0
- package/lib/utils/ReachabilityMonitor/index.native.js.map +1 -0
- package/lib/utils/ReconnectionMonitor.d.ts +29 -0
- package/lib/utils/ReconnectionMonitor.js +73 -0
- package/lib/utils/ReconnectionMonitor.js.map +1 -0
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.d.ts +10 -2
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.js +129 -86
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/index.js.map +1 -1
- package/lib-esm/Providers/MqttOverWSProvider.d.ts +5 -1
- package/lib-esm/Providers/MqttOverWSProvider.js +153 -88
- package/lib-esm/Providers/MqttOverWSProvider.js.map +1 -1
- package/lib-esm/Providers/PubSubProvider.d.ts +1 -1
- package/lib-esm/Providers/{AWSAppSyncRealTimeProvider/constants.d.ts → constants.d.ts} +9 -0
- package/lib-esm/Providers/{AWSAppSyncRealTimeProvider/constants.js → constants.js} +9 -0
- package/lib-esm/Providers/constants.js.map +1 -0
- package/lib-esm/index.d.ts +3 -10
- package/lib-esm/index.js +3 -11
- package/lib-esm/index.js.map +1 -1
- package/lib-esm/types/Provider.d.ts +10 -1
- package/lib-esm/types/PubSub.d.ts +22 -8
- package/lib-esm/types/PubSub.js +56 -0
- package/lib-esm/types/PubSub.js.map +1 -1
- package/lib-esm/types/index.d.ts +0 -17
- package/lib-esm/types/index.js +1 -36
- package/lib-esm/types/index.js.map +1 -1
- package/lib-esm/utils/ConnectionStateMonitor.d.ts +2 -1
- package/lib-esm/utils/ConnectionStateMonitor.js +13 -5
- package/lib-esm/utils/ConnectionStateMonitor.js.map +1 -1
- package/lib-esm/utils/ReachabilityMonitor/index.d.ts +3 -0
- package/lib-esm/utils/ReachabilityMonitor/index.js +3 -0
- package/lib-esm/utils/ReachabilityMonitor/index.js.map +1 -0
- package/lib-esm/utils/ReachabilityMonitor/index.native.d.ts +3 -0
- package/lib-esm/utils/ReachabilityMonitor/index.native.js +6 -0
- package/lib-esm/utils/ReachabilityMonitor/index.native.js.map +1 -0
- package/lib-esm/utils/ReconnectionMonitor.d.ts +29 -0
- package/lib-esm/utils/ReconnectionMonitor.js +71 -0
- package/lib-esm/utils/ReconnectionMonitor.js.map +1 -0
- package/package.json +5 -5
- package/src/Providers/AWSAppSyncRealTimeProvider/index.ts +154 -90
- package/src/Providers/MqttOverWSProvider.ts +120 -53
- package/src/Providers/PubSubProvider.ts +1 -1
- package/src/Providers/{AWSAppSyncRealTimeProvider/constants.ts → constants.ts} +12 -0
- package/src/index.ts +3 -10
- package/src/types/Provider.ts +13 -1
- package/src/types/PubSub.ts +47 -8
- package/src/types/index.ts +0 -43
- package/src/utils/ConnectionStateMonitor.ts +20 -5
- package/src/utils/ReachabilityMonitor/index.native.ts +5 -0
- package/src/utils/ReachabilityMonitor/index.ts +3 -0
- package/src/utils/ReconnectionMonitor.ts +74 -0
- package/lib/Providers/AWSAppSyncRealTimeProvider/constants.js.map +0 -1
- package/lib-esm/Providers/AWSAppSyncRealTimeProvider/constants.js.map +0 -1
|
@@ -12,11 +12,21 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import * as Paho from 'paho-mqtt';
|
|
14
14
|
import { v4 as uuid } from 'uuid';
|
|
15
|
-
import Observable from 'zen-observable-ts';
|
|
15
|
+
import Observable, { ZenObservable } from 'zen-observable-ts';
|
|
16
16
|
|
|
17
17
|
import { AbstractPubSubProvider } from './PubSubProvider';
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
18
|
+
import { SubscriptionObserver, ConnectionState } from '../types/PubSub';
|
|
19
|
+
import { ProviderOptions } from '../types/Provider';
|
|
20
|
+
import { ConsoleLogger as Logger, Hub } from '@aws-amplify/core';
|
|
21
|
+
import {
|
|
22
|
+
ConnectionStateMonitor,
|
|
23
|
+
CONNECTION_CHANGE,
|
|
24
|
+
} from '../utils/ConnectionStateMonitor';
|
|
25
|
+
import {
|
|
26
|
+
ReconnectEvent,
|
|
27
|
+
ReconnectionMonitor,
|
|
28
|
+
} from '../utils/ReconnectionMonitor';
|
|
29
|
+
import { AMPLIFY_SYMBOL, CONNECTION_STATE_CHANGE } from './constants';
|
|
20
30
|
|
|
21
31
|
const logger = new Logger('MqttOverWSProvider');
|
|
22
32
|
|
|
@@ -49,17 +59,15 @@ class ClientsQueue {
|
|
|
49
59
|
|
|
50
60
|
async get(clientId: string, clientFactory?: (input: string) => Promise<any>) {
|
|
51
61
|
const cachedPromise = this.promises.get(clientId);
|
|
52
|
-
if (cachedPromise)
|
|
53
|
-
return cachedPromise;
|
|
54
|
-
}
|
|
62
|
+
if (cachedPromise) return cachedPromise;
|
|
55
63
|
|
|
56
64
|
if (clientFactory) {
|
|
57
65
|
const newPromise = clientFactory(clientId);
|
|
58
|
-
|
|
59
66
|
this.promises.set(clientId, newPromise);
|
|
60
|
-
|
|
67
|
+
newPromise.catch(v => this.promises.delete(clientId));
|
|
61
68
|
return newPromise;
|
|
62
69
|
}
|
|
70
|
+
|
|
63
71
|
return undefined;
|
|
64
72
|
}
|
|
65
73
|
|
|
@@ -72,13 +80,44 @@ class ClientsQueue {
|
|
|
72
80
|
}
|
|
73
81
|
}
|
|
74
82
|
|
|
83
|
+
const dispatchPubSubEvent = (event: string, data: any, message: string) => {
|
|
84
|
+
Hub.dispatch('pubsub', { event, data, message }, 'PubSub', AMPLIFY_SYMBOL);
|
|
85
|
+
};
|
|
86
|
+
|
|
75
87
|
const topicSymbol = typeof Symbol !== 'undefined' ? Symbol('topic') : '@@topic';
|
|
76
88
|
|
|
77
89
|
export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
78
90
|
private _clientsQueue = new ClientsQueue();
|
|
91
|
+
private connectionState: ConnectionState;
|
|
92
|
+
private readonly connectionStateMonitor = new ConnectionStateMonitor();
|
|
93
|
+
private readonly reconnectionMonitor = new ReconnectionMonitor();
|
|
79
94
|
|
|
80
95
|
constructor(options: MqttProviderOptions = {}) {
|
|
81
96
|
super({ ...options, clientId: options.clientId || uuid() });
|
|
97
|
+
|
|
98
|
+
// Monitor the connection health state and pass changes along to Hub
|
|
99
|
+
this.connectionStateMonitor.connectionStateObservable.subscribe(
|
|
100
|
+
connectionStateChange => {
|
|
101
|
+
dispatchPubSubEvent(
|
|
102
|
+
CONNECTION_STATE_CHANGE,
|
|
103
|
+
{
|
|
104
|
+
provider: this,
|
|
105
|
+
connectionState: connectionStateChange,
|
|
106
|
+
},
|
|
107
|
+
`Connection state is ${connectionStateChange}`
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
this.connectionState = connectionStateChange;
|
|
111
|
+
|
|
112
|
+
// Trigger reconnection when the connection is disrupted
|
|
113
|
+
if (connectionStateChange === ConnectionState.ConnectionDisrupted) {
|
|
114
|
+
this.reconnectionMonitor.record(ReconnectEvent.START_RECONNECT);
|
|
115
|
+
} else if (connectionStateChange !== ConnectionState.Connecting) {
|
|
116
|
+
// Trigger connected to halt reconnection attempts
|
|
117
|
+
this.reconnectionMonitor.record(ReconnectEvent.HALT_RECONNECT);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
);
|
|
82
121
|
}
|
|
83
122
|
|
|
84
123
|
protected get clientId() {
|
|
@@ -117,7 +156,6 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
117
156
|
if (errorCode !== 0) {
|
|
118
157
|
logger.warn(clientId, JSON.stringify({ errorCode, ...args }, null, 2));
|
|
119
158
|
|
|
120
|
-
const topicsToDelete: string[] = [];
|
|
121
159
|
if (!clientId) {
|
|
122
160
|
return;
|
|
123
161
|
}
|
|
@@ -125,33 +163,17 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
125
163
|
if (!clientIdObservers) {
|
|
126
164
|
return;
|
|
127
165
|
}
|
|
128
|
-
|
|
129
|
-
observer.error('Disconnected, error code: ' + errorCode);
|
|
130
|
-
// removing observers for disconnected clientId
|
|
131
|
-
this._topicObservers.forEach((observerForTopic, observerTopic) => {
|
|
132
|
-
observerForTopic.delete(observer);
|
|
133
|
-
if (observerForTopic.size === 0) {
|
|
134
|
-
topicsToDelete.push(observerTopic);
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
// forgiving any trace of clientId
|
|
140
|
-
this._clientIdObservers.delete(clientId);
|
|
141
|
-
|
|
142
|
-
// Removing topics that are not listen by an observer
|
|
143
|
-
topicsToDelete.forEach(topic => {
|
|
144
|
-
this._topicObservers.delete(topic);
|
|
145
|
-
});
|
|
166
|
+
this.disconnect(clientId);
|
|
146
167
|
}
|
|
147
168
|
}
|
|
148
169
|
|
|
149
170
|
public async newClient({ url, clientId }: MqttProviderOptions): Promise<any> {
|
|
150
171
|
logger.debug('Creating new MQTT client', clientId);
|
|
151
172
|
|
|
173
|
+
this.connectionStateMonitor.record(CONNECTION_CHANGE.OPENING_CONNECTION);
|
|
152
174
|
// @ts-ignore
|
|
153
175
|
const client = new Paho.Client(url, clientId);
|
|
154
|
-
|
|
176
|
+
|
|
155
177
|
client.onMessageArrived = ({
|
|
156
178
|
destinationName: topic,
|
|
157
179
|
payloadString: msg,
|
|
@@ -168,17 +190,28 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
168
190
|
errorCode: number;
|
|
169
191
|
}) => {
|
|
170
192
|
this.onDisconnect({ clientId, errorCode, ...args });
|
|
193
|
+
this.connectionStateMonitor.record(CONNECTION_CHANGE.CLOSED);
|
|
171
194
|
};
|
|
172
195
|
|
|
173
|
-
await new Promise((resolve, reject) => {
|
|
196
|
+
const connected = await new Promise((resolve, reject) => {
|
|
174
197
|
client.connect({
|
|
175
198
|
useSSL: this.isSSLEnabled,
|
|
176
199
|
mqttVersion: 3,
|
|
177
|
-
onSuccess: () => resolve(
|
|
178
|
-
onFailure:
|
|
200
|
+
onSuccess: () => resolve(true),
|
|
201
|
+
onFailure: x => {
|
|
202
|
+
if (clientId) this._clientsQueue.remove(clientId);
|
|
203
|
+
this.connectionStateMonitor.record(CONNECTION_CHANGE.CLOSED);
|
|
204
|
+
resolve(false);
|
|
205
|
+
},
|
|
179
206
|
});
|
|
180
207
|
});
|
|
181
208
|
|
|
209
|
+
if (connected) {
|
|
210
|
+
this.connectionStateMonitor.record(
|
|
211
|
+
CONNECTION_CHANGE.CONNECTION_ESTABLISHED
|
|
212
|
+
);
|
|
213
|
+
}
|
|
214
|
+
|
|
182
215
|
return client;
|
|
183
216
|
}
|
|
184
217
|
|
|
@@ -186,9 +219,19 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
186
219
|
clientId: string,
|
|
187
220
|
options: MqttProviderOptions = {}
|
|
188
221
|
): Promise<any> {
|
|
189
|
-
return await this.clientsQueue.get(clientId, clientId =>
|
|
190
|
-
this.newClient({ ...options, clientId })
|
|
191
|
-
|
|
222
|
+
return await this.clientsQueue.get(clientId, async clientId => {
|
|
223
|
+
const client = await this.newClient({ ...options, clientId });
|
|
224
|
+
|
|
225
|
+
if (client) {
|
|
226
|
+
// Once connected, subscribe to all topics registered observers
|
|
227
|
+
this._topicObservers.forEach(
|
|
228
|
+
(_value: Set<SubscriptionObserver<any>>, key: string) => {
|
|
229
|
+
client.subscribe(key);
|
|
230
|
+
}
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return client;
|
|
234
|
+
});
|
|
192
235
|
}
|
|
193
236
|
|
|
194
237
|
protected async disconnect(clientId: string): Promise<void> {
|
|
@@ -198,18 +241,25 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
198
241
|
client.disconnect();
|
|
199
242
|
}
|
|
200
243
|
this.clientsQueue.remove(clientId);
|
|
244
|
+
this.connectionStateMonitor.record(CONNECTION_CHANGE.CLOSED);
|
|
201
245
|
}
|
|
202
246
|
|
|
203
247
|
async publish(topics: string[] | string, msg: any) {
|
|
204
248
|
const targetTopics = ([] as string[]).concat(topics);
|
|
205
249
|
const message = JSON.stringify(msg);
|
|
206
250
|
|
|
207
|
-
const
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
251
|
+
const client = await this.clientsQueue.get(this.clientId);
|
|
252
|
+
|
|
253
|
+
if (client) {
|
|
254
|
+
logger.debug('Publishing to topic(s)', targetTopics.join(','), message);
|
|
255
|
+
targetTopics.forEach(topic => client.send(topic, message));
|
|
256
|
+
} else {
|
|
257
|
+
logger.debug(
|
|
258
|
+
'Publishing to topic(s) failed',
|
|
259
|
+
targetTopics.join(','),
|
|
260
|
+
message
|
|
261
|
+
);
|
|
262
|
+
}
|
|
213
263
|
}
|
|
214
264
|
|
|
215
265
|
protected _topicObservers: Map<string, Set<SubscriptionObserver<any>>> =
|
|
@@ -246,6 +296,7 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
246
296
|
): Observable<any> {
|
|
247
297
|
const targetTopics = ([] as string[]).concat(topics);
|
|
248
298
|
logger.debug('Subscribing to topic(s)', targetTopics.join(','));
|
|
299
|
+
let reconnectSubscription: ZenObservable.Subscription;
|
|
249
300
|
|
|
250
301
|
return new Observable(observer => {
|
|
251
302
|
targetTopics.forEach(topic => {
|
|
@@ -261,8 +312,6 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
261
312
|
observersForTopic.add(observer);
|
|
262
313
|
});
|
|
263
314
|
|
|
264
|
-
// @ts-ignore
|
|
265
|
-
let client: Paho.Client;
|
|
266
315
|
const { clientId = this.clientId } = options;
|
|
267
316
|
|
|
268
317
|
// this._clientIdObservers is used to close observers when client gets disconnected
|
|
@@ -274,26 +323,44 @@ export class MqttOverWSProvider extends AbstractPubSubProvider {
|
|
|
274
323
|
this._clientIdObservers.set(clientId, observersForClientId);
|
|
275
324
|
|
|
276
325
|
(async () => {
|
|
277
|
-
const
|
|
326
|
+
const getClient = async () => {
|
|
327
|
+
try {
|
|
328
|
+
const { url = await this.endpoint } = options;
|
|
329
|
+
const client = await this.connect(clientId, { url });
|
|
330
|
+
if (client !== undefined) {
|
|
331
|
+
targetTopics.forEach(topic => {
|
|
332
|
+
client.subscribe(topic);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
} catch (e) {
|
|
336
|
+
logger.debug('Error forming connection', e);
|
|
337
|
+
}
|
|
338
|
+
};
|
|
278
339
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
340
|
+
// Establish the initial connection
|
|
341
|
+
await getClient();
|
|
342
|
+
|
|
343
|
+
// Add an observable to the reconnection list to manage reconnection for this subscription
|
|
344
|
+
reconnectSubscription = new Observable(observer => {
|
|
345
|
+
this.reconnectionMonitor.addObserver(observer);
|
|
346
|
+
}).subscribe(() => {
|
|
347
|
+
getClient();
|
|
348
|
+
});
|
|
287
349
|
})();
|
|
288
350
|
|
|
289
|
-
return () => {
|
|
290
|
-
|
|
351
|
+
return async () => {
|
|
352
|
+
const client = await this.clientsQueue.get(clientId);
|
|
353
|
+
|
|
354
|
+
reconnectSubscription?.unsubscribe();
|
|
291
355
|
|
|
292
356
|
if (client) {
|
|
293
357
|
this._clientIdObservers.get(clientId)?.delete(observer);
|
|
294
358
|
// No more observers per client => client not needed anymore
|
|
295
359
|
if (this._clientIdObservers.get(clientId)?.size === 0) {
|
|
296
360
|
this.disconnect(clientId);
|
|
361
|
+
this.connectionStateMonitor.record(
|
|
362
|
+
CONNECTION_CHANGE.CLOSING_CONNECTION
|
|
363
|
+
);
|
|
297
364
|
this._clientIdObservers.delete(clientId);
|
|
298
365
|
}
|
|
299
366
|
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
import Observable from 'zen-observable-ts';
|
|
14
|
-
import { PubSubProvider, ProviderOptions } from '../types';
|
|
14
|
+
import { PubSubProvider, ProviderOptions } from '../types/Provider';
|
|
15
15
|
import { ConsoleLogger as Logger } from '@aws-amplify/core';
|
|
16
16
|
|
|
17
17
|
const logger = new Logger('AbstractPubSubProvider');
|
|
@@ -2,6 +2,8 @@ export const MAX_DELAY_MS = 5000;
|
|
|
2
2
|
|
|
3
3
|
export const NON_RETRYABLE_CODES = [400, 401, 403];
|
|
4
4
|
|
|
5
|
+
export const CONNECTION_STATE_CHANGE = 'ConnectionStateChange';
|
|
6
|
+
|
|
5
7
|
export enum MESSAGE_TYPES {
|
|
6
8
|
/**
|
|
7
9
|
* Client -> Server message.
|
|
@@ -98,3 +100,13 @@ export const DEFAULT_KEEP_ALIVE_TIMEOUT = 5 * 60 * 1000;
|
|
|
98
100
|
* Default Time in milleseconds to alert for missed GQL_CONNECTION_KEEP_ALIVE message
|
|
99
101
|
*/
|
|
100
102
|
export const DEFAULT_KEEP_ALIVE_ALERT_TIMEOUT = 65 * 1000;
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Default delay time in milleseconds between when reconnect is triggered vs when it is attempted
|
|
106
|
+
*/
|
|
107
|
+
export const RECONNECT_DELAY = 5 * 1000;
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Default interval time in milleseconds between when reconnect is re-attempted
|
|
111
|
+
*/
|
|
112
|
+
export const RECONNECT_INTERVAL = 60 * 1000;
|
package/src/index.ts
CHANGED
|
@@ -14,18 +14,11 @@ import { PubSub } from './PubSub';
|
|
|
14
14
|
|
|
15
15
|
export * from './Providers';
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
CONNECTION_CLOSED = 'Connection closed',
|
|
19
|
-
CONNECTION_FAILED = 'Connection failed',
|
|
20
|
-
REALTIME_SUBSCRIPTION_INIT_ERROR = 'AppSync Realtime subscription init error',
|
|
21
|
-
SUBSCRIPTION_ACK = 'Subscription ack',
|
|
22
|
-
TIMEOUT_DISCONNECT = 'Timeout disconnect',
|
|
23
|
-
}
|
|
17
|
+
export { CONNECTION_STATE_CHANGE } from './Providers/constants';
|
|
24
18
|
|
|
25
|
-
export
|
|
26
|
-
export { ConnectionState } from './types';
|
|
19
|
+
export { ConnectionState, CONTROL_MSG } from './types';
|
|
27
20
|
|
|
28
|
-
export { PubSub
|
|
21
|
+
export { PubSub };
|
|
29
22
|
|
|
30
23
|
/**
|
|
31
24
|
* @deprecated use named import
|
package/src/types/Provider.ts
CHANGED
|
@@ -11,7 +11,19 @@
|
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
13
|
import Observable from 'zen-observable-ts';
|
|
14
|
-
|
|
14
|
+
|
|
15
|
+
export interface PubSubOptions {
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface ProviderOptions {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @deprecated Migrated to ProviderOptions
|
|
25
|
+
*/
|
|
26
|
+
export type ProvidertOptions = ProviderOptions;
|
|
15
27
|
|
|
16
28
|
export interface PubSubProvider {
|
|
17
29
|
// configure your provider
|
package/src/types/PubSub.ts
CHANGED
|
@@ -10,15 +10,54 @@
|
|
|
10
10
|
* CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions
|
|
11
11
|
* and limitations under the License.
|
|
12
12
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
export interface SubscriptionObserver<T> {
|
|
15
|
+
closed: boolean;
|
|
16
|
+
next(value: T): void;
|
|
17
|
+
error(errorValue: any): void;
|
|
18
|
+
complete(): void;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
|
-
export
|
|
18
|
-
|
|
21
|
+
export enum CONTROL_MSG {
|
|
22
|
+
CONNECTION_CLOSED = 'Connection closed',
|
|
23
|
+
CONNECTION_FAILED = 'Connection failed',
|
|
24
|
+
REALTIME_SUBSCRIPTION_INIT_ERROR = 'AppSync Realtime subscription init error',
|
|
25
|
+
SUBSCRIPTION_ACK = 'Subscription ack',
|
|
26
|
+
TIMEOUT_DISCONNECT = 'Timeout disconnect',
|
|
19
27
|
}
|
|
20
28
|
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
29
|
+
/** @enum {string} */
|
|
30
|
+
export enum ConnectionState {
|
|
31
|
+
/*
|
|
32
|
+
* The connection is alive and healthy
|
|
33
|
+
*/
|
|
34
|
+
Connected = 'Connected',
|
|
35
|
+
/*
|
|
36
|
+
* The connection is alive, but the connection is offline
|
|
37
|
+
*/
|
|
38
|
+
ConnectedPendingNetwork = 'ConnectedPendingNetwork',
|
|
39
|
+
/*
|
|
40
|
+
* The connection has been disconnected while in use
|
|
41
|
+
*/
|
|
42
|
+
ConnectionDisrupted = 'ConnectionDisrupted',
|
|
43
|
+
/*
|
|
44
|
+
* The connection has been disconnected and the network is offline
|
|
45
|
+
*/
|
|
46
|
+
ConnectionDisruptedPendingNetwork = 'ConnectionDisruptedPendingNetwork',
|
|
47
|
+
/*
|
|
48
|
+
* The connection is in the process of connecting
|
|
49
|
+
*/
|
|
50
|
+
Connecting = 'Connecting',
|
|
51
|
+
/*
|
|
52
|
+
* The connection is not in use and is being disconnected
|
|
53
|
+
*/
|
|
54
|
+
ConnectedPendingDisconnect = 'ConnectedPendingDisconnect',
|
|
55
|
+
/*
|
|
56
|
+
* The connection is not in use and has been disconnected
|
|
57
|
+
*/
|
|
58
|
+
Disconnected = 'Disconnected',
|
|
59
|
+
/*
|
|
60
|
+
* The connection is alive, but a keep alive message has been missed
|
|
61
|
+
*/
|
|
62
|
+
ConnectedPendingKeepAlive = 'ConnectedPendingKeepAlive',
|
|
63
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -12,46 +12,3 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export * from './Provider';
|
|
14
14
|
export * from './PubSub';
|
|
15
|
-
|
|
16
|
-
export interface SubscriptionObserver<T> {
|
|
17
|
-
closed: boolean;
|
|
18
|
-
next(value: T): void;
|
|
19
|
-
error(errorValue: any): void;
|
|
20
|
-
complete(): void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/** @enum {string} */
|
|
24
|
-
export enum ConnectionState {
|
|
25
|
-
/*
|
|
26
|
-
* The connection is alive and healthy
|
|
27
|
-
*/
|
|
28
|
-
Connected = 'Connected',
|
|
29
|
-
/*
|
|
30
|
-
* The connection is alive, but the connection is offline
|
|
31
|
-
*/
|
|
32
|
-
ConnectedPendingNetwork = 'ConnectedPendingNetwork',
|
|
33
|
-
/*
|
|
34
|
-
* The connection has been disconnected while in use
|
|
35
|
-
*/
|
|
36
|
-
ConnectionDisrupted = 'ConnectionDisrupted',
|
|
37
|
-
/*
|
|
38
|
-
* The connection has been disconnected and the network is offline
|
|
39
|
-
*/
|
|
40
|
-
ConnectionDisruptedPendingNetwork = 'ConnectionDisruptedPendingNetwork',
|
|
41
|
-
/*
|
|
42
|
-
* The connection is in the process of connecting
|
|
43
|
-
*/
|
|
44
|
-
Connecting = 'Connecting',
|
|
45
|
-
/*
|
|
46
|
-
* The connection is not in use and is being disconnected
|
|
47
|
-
*/
|
|
48
|
-
ConnectedPendingDisconnect = 'ConnectedPendingDisconnect',
|
|
49
|
-
/*
|
|
50
|
-
* The connection is not in use and has been disconnected
|
|
51
|
-
*/
|
|
52
|
-
Disconnected = 'Disconnected',
|
|
53
|
-
/*
|
|
54
|
-
* The connection is alive, but a keep alive message has been missed
|
|
55
|
-
*/
|
|
56
|
-
ConnectedPendingKeepAlive = 'ConnectedPendingKeepAlive',
|
|
57
|
-
}
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import { Reachability } from '@aws-amplify/core';
|
|
15
15
|
import Observable, { ZenObservable } from 'zen-observable-ts';
|
|
16
|
-
import { ConnectionState } from '../
|
|
16
|
+
import { ConnectionState } from '../types/PubSub';
|
|
17
|
+
import { ReachabilityMonitor } from './ReachabilityMonitor';
|
|
17
18
|
|
|
18
19
|
// Internal types for tracking different connection states
|
|
19
20
|
type LinkedConnectionState = 'connected' | 'disconnected';
|
|
@@ -62,6 +63,7 @@ export class ConnectionStateMonitor {
|
|
|
62
63
|
private _linkedConnectionStateObservable: Observable<LinkedConnectionStates>;
|
|
63
64
|
private _linkedConnectionStateObserver: ZenObservable.SubscriptionObserver<LinkedConnectionStates>;
|
|
64
65
|
private _networkMonitoringSubscription?: ZenObservable.Subscription;
|
|
66
|
+
private _initialNetworkStateSubscription?: ZenObservable.Subscription;
|
|
65
67
|
|
|
66
68
|
constructor() {
|
|
67
69
|
this._networkMonitoringSubscription = undefined;
|
|
@@ -72,6 +74,16 @@ export class ConnectionStateMonitor {
|
|
|
72
74
|
keepAliveState: 'healthy',
|
|
73
75
|
};
|
|
74
76
|
|
|
77
|
+
// Attempt to update the state with the current actual network state
|
|
78
|
+
this._initialNetworkStateSubscription = ReachabilityMonitor().subscribe(
|
|
79
|
+
({ online }) => {
|
|
80
|
+
this.record(
|
|
81
|
+
online ? CONNECTION_CHANGE.ONLINE : CONNECTION_CHANGE.OFFLINE
|
|
82
|
+
);
|
|
83
|
+
this._initialNetworkStateSubscription?.unsubscribe();
|
|
84
|
+
}
|
|
85
|
+
);
|
|
86
|
+
|
|
75
87
|
this._linkedConnectionStateObservable =
|
|
76
88
|
new Observable<LinkedConnectionStates>(connectionStateObserver => {
|
|
77
89
|
connectionStateObserver.next(this._linkedConnectionState);
|
|
@@ -83,15 +95,18 @@ export class ConnectionStateMonitor {
|
|
|
83
95
|
* Turn network state monitoring on if it isn't on already
|
|
84
96
|
*/
|
|
85
97
|
private enableNetworkMonitoring() {
|
|
98
|
+
// If no initial network state was discovered, stop trying
|
|
99
|
+
this._initialNetworkStateSubscription?.unsubscribe();
|
|
100
|
+
|
|
86
101
|
// Maintain the network state based on the reachability monitor
|
|
87
102
|
if (this._networkMonitoringSubscription === undefined) {
|
|
88
|
-
this._networkMonitoringSubscription =
|
|
89
|
-
|
|
90
|
-
.subscribe(({ online }) => {
|
|
103
|
+
this._networkMonitoringSubscription = ReachabilityMonitor().subscribe(
|
|
104
|
+
({ online }) => {
|
|
91
105
|
this.record(
|
|
92
106
|
online ? CONNECTION_CHANGE.ONLINE : CONNECTION_CHANGE.OFFLINE
|
|
93
107
|
);
|
|
94
|
-
}
|
|
108
|
+
}
|
|
109
|
+
);
|
|
95
110
|
}
|
|
96
111
|
}
|
|
97
112
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Observer } from 'zen-observable-ts';
|
|
2
|
+
import { RECONNECT_DELAY, RECONNECT_INTERVAL } from '../Providers/constants';
|
|
3
|
+
|
|
4
|
+
export enum ReconnectEvent {
|
|
5
|
+
START_RECONNECT = 'START_RECONNECT',
|
|
6
|
+
HALT_RECONNECT = 'HALT_RECONNECT',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Captures the reconnect event logic used to determine when to reconnect to PubSub providers.
|
|
11
|
+
* Reconnnect attempts are delayed by 5 seconds to let the interface settle.
|
|
12
|
+
* Attempting to reconnect only once creates unrecoverable states when the network state isn't
|
|
13
|
+
* supported by the browser, so this keeps retrying every minute until halted.
|
|
14
|
+
*/
|
|
15
|
+
export class ReconnectionMonitor {
|
|
16
|
+
private reconnectObservers: Observer<void>[] = [];
|
|
17
|
+
private reconnectIntervalId?: ReturnType<typeof setInterval>;
|
|
18
|
+
private reconnectSetTimeoutId?: ReturnType<typeof setTimeout>;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Add reconnect observer to the list of observers to alert on reconnect
|
|
22
|
+
*/
|
|
23
|
+
addObserver(reconnectObserver: Observer<void>) {
|
|
24
|
+
this.reconnectObservers.push(reconnectObserver);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Given a reconnect event, start the appropriate behavior
|
|
29
|
+
*/
|
|
30
|
+
record(event: ReconnectEvent) {
|
|
31
|
+
if (event === ReconnectEvent.START_RECONNECT) {
|
|
32
|
+
// If the reconnection hasn't been started
|
|
33
|
+
if (
|
|
34
|
+
this.reconnectSetTimeoutId === undefined &&
|
|
35
|
+
this.reconnectIntervalId === undefined
|
|
36
|
+
) {
|
|
37
|
+
this.reconnectSetTimeoutId = setTimeout(() => {
|
|
38
|
+
// Reconnect now
|
|
39
|
+
this._triggerReconnect();
|
|
40
|
+
// Retry reconnect every periodically until it works
|
|
41
|
+
this.reconnectIntervalId = setInterval(() => {
|
|
42
|
+
this._triggerReconnect();
|
|
43
|
+
}, RECONNECT_INTERVAL);
|
|
44
|
+
}, RECONNECT_DELAY);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (event === ReconnectEvent.HALT_RECONNECT) {
|
|
49
|
+
if (this.reconnectIntervalId) {
|
|
50
|
+
clearInterval(this.reconnectIntervalId);
|
|
51
|
+
this.reconnectIntervalId = undefined;
|
|
52
|
+
}
|
|
53
|
+
if (this.reconnectSetTimeoutId) {
|
|
54
|
+
clearTimeout(this.reconnectSetTimeoutId);
|
|
55
|
+
this.reconnectSetTimeoutId = undefined;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Complete all reconnect observers
|
|
62
|
+
*/
|
|
63
|
+
close() {
|
|
64
|
+
this.reconnectObservers.forEach(reconnectObserver => {
|
|
65
|
+
reconnectObserver.complete?.();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private _triggerReconnect() {
|
|
70
|
+
this.reconnectObservers.forEach(reconnectObserver => {
|
|
71
|
+
reconnectObserver.next?.();
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/Providers/AWSAppSyncRealTimeProvider/constants.ts"],"names":[],"mappings":";;AAAa,QAAA,YAAY,GAAG,IAAI,CAAC;AAEpB,QAAA,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnD,IAAY,aAmDX;AAnDD,WAAY,aAAa;IACxB;;;OAGG;IACH,wDAAuC,CAAA;IACvC;;;OAGG;IACH,0DAAyC,CAAA;IACzC;;;OAGG;IACH,sDAAqC,CAAA;IACrC;;;OAGG;IACH,oCAAmB,CAAA;IACnB;;;OAGG;IACH,4CAA2B,CAAA;IAC3B;;;OAGG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,iDAAgC,CAAA;IAChC;;;OAGG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,0CAAyB,CAAA;IACzB;;;OAGG;IACH,oCAAmB,CAAA;AACpB,CAAC,EAnDW,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAmDxB;AAED,IAAY,mBAIX;AAJD,WAAY,mBAAmB;IAC9B,mEAAO,CAAA;IACP,uEAAS,CAAA;IACT,iEAAM,CAAA;AACP,CAAC,EAJW,mBAAmB,GAAnB,2BAAmB,KAAnB,2BAAmB,QAI9B;AAED,IAAY,aAIX;AAJD,WAAY,aAAa;IACxB,qDAAM,CAAA;IACN,mDAAK,CAAA;IACL,6DAAU,CAAA;AACX,CAAC,EAJW,aAAa,GAAb,qBAAa,KAAb,qBAAa,QAIxB;AAEY,QAAA,cAAc,GAAG,CAC7B,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,UAAU;IAChE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/B,CAAC,CAAC,mBAAmB,CACZ,CAAC;AAEC,QAAA,4BAA4B,GAAG;IAC3C,MAAM,EAAE,mCAAmC;IAC3C,kBAAkB,EAAE,SAAS;IAC7B,cAAc,EAAE,iCAAiC;CACjD,CAAC;AAEF;;GAEG;AACU,QAAA,uBAAuB,GAAG,KAAK,CAAC;AAE7C;;GAEG;AACU,QAAA,iBAAiB,GAAG,KAAK,CAAC;AAEvC;;GAEG;AACU,QAAA,0BAA0B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAExD;;GAEG;AACU,QAAA,gCAAgC,GAAG,EAAE,GAAG,IAAI,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/Providers/AWSAppSyncRealTimeProvider/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,IAAM,YAAY,GAAG,IAAI,CAAC;AAEjC,MAAM,CAAC,IAAM,mBAAmB,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAEnD,MAAM,CAAN,IAAY,aAmDX;AAnDD,WAAY,aAAa;IACxB;;;OAGG;IACH,wDAAuC,CAAA;IACvC;;;OAGG;IACH,0DAAyC,CAAA;IACzC;;;OAGG;IACH,sDAAqC,CAAA;IACrC;;;OAGG;IACH,oCAAmB,CAAA;IACnB;;;OAGG;IACH,4CAA2B,CAAA;IAC3B;;;OAGG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,iDAAgC,CAAA;IAChC;;;OAGG;IACH,kCAAiB,CAAA;IACjB;;;OAGG;IACH,0CAAyB,CAAA;IACzB;;;OAGG;IACH,oCAAmB,CAAA;AACpB,CAAC,EAnDW,aAAa,KAAb,aAAa,QAmDxB;AAED,MAAM,CAAN,IAAY,mBAIX;AAJD,WAAY,mBAAmB;IAC9B,mEAAO,CAAA;IACP,uEAAS,CAAA;IACT,iEAAM,CAAA;AACP,CAAC,EAJW,mBAAmB,KAAnB,mBAAmB,QAI9B;AAED,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACxB,qDAAM,CAAA;IACN,mDAAK,CAAA;IACL,6DAAU,CAAA;AACX,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AAED,MAAM,CAAC,IAAM,cAAc,GAAG,CAC7B,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,UAAU;IAChE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAC/B,CAAC,CAAC,mBAAmB,CACZ,CAAC;AAEZ,MAAM,CAAC,IAAM,4BAA4B,GAAG;IAC3C,MAAM,EAAE,mCAAmC;IAC3C,kBAAkB,EAAE,SAAS;IAC7B,cAAc,EAAE,iCAAiC;CACjD,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,IAAM,uBAAuB,GAAG,KAAK,CAAC;AAE7C;;GAEG;AACH,MAAM,CAAC,IAAM,iBAAiB,GAAG,KAAK,CAAC;AAEvC;;GAEG;AACH,MAAM,CAAC,IAAM,0BAA0B,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;AAExD;;GAEG;AACH,MAAM,CAAC,IAAM,gCAAgC,GAAG,EAAE,GAAG,IAAI,CAAC"}
|