Skip to content

Commit df1b588

Browse files
author
Brian Chen
authored
Add ConnectivityMonitor to Firestore(#1808)
1 parent 4771184 commit df1b588

File tree

7 files changed

+166
-0
lines changed

7 files changed

+166
-0
lines changed

packages/firestore/src/platform/platform.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ProtoByteString } from '../core/types';
2020
import { Connection } from '../remote/connection';
2121
import { JsonProtoSerializer } from '../remote/serializer';
2222
import { fail } from '../util/assert';
23+
import { ConnectivityMonitor } from './../remote/connectivity_monitor';
2324

2425
/**
2526
* Provides a common interface to load anything platform dependent, e.g.
@@ -31,6 +32,7 @@ import { fail } from '../util/assert';
3132
// use in our client.
3233
export interface Platform {
3334
loadConnection(databaseInfo: DatabaseInfo): Promise<Connection>;
35+
newConnectivityMonitor(): ConnectivityMonitor;
3436
newSerializer(databaseId: DatabaseId): JsonProtoSerializer;
3537

3638
/** Formats an object as a JSON string, suitable for logging. */
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { debug } from '../util/log';
19+
import {
20+
ConnectivityMonitor,
21+
ConnectivityMonitorCallback,
22+
NetworkStatus
23+
} from './../remote/connectivity_monitor';
24+
25+
const LOG_TAG = 'ConnectivityMonitor';
26+
27+
/**
28+
* Browser implementation of ConnectivityMonitor.
29+
*/
30+
export class BrowserConnectivityMonitor implements ConnectivityMonitor {
31+
private readonly networkAvailableListener = () => this.onNetworkAvailable();
32+
private readonly networkUnavailableListener = () =>
33+
this.onNetworkUnavailable();
34+
private callbacks: ConnectivityMonitorCallback[] = [];
35+
36+
constructor() {
37+
this.configureNetworkMonitoring();
38+
}
39+
40+
addCallback(callback: (status: NetworkStatus) => void): void {
41+
this.callbacks.push(callback);
42+
}
43+
44+
shutdown(): void {
45+
window.removeEventListener('online', this.networkAvailableListener);
46+
window.removeEventListener('offline', this.networkUnavailableListener);
47+
}
48+
49+
private configureNetworkMonitoring(): void {
50+
window.addEventListener('online', this.networkAvailableListener);
51+
window.addEventListener('offline', this.networkUnavailableListener);
52+
}
53+
54+
private onNetworkAvailable(): void {
55+
debug(LOG_TAG, 'Network connectivity changed: AVAILABLE');
56+
for (const callback of this.callbacks) {
57+
callback(NetworkStatus.AVAILABLE);
58+
}
59+
}
60+
61+
private onNetworkUnavailable(): void {
62+
debug(LOG_TAG, 'Network connectivity changed: UNAVAILABLE');
63+
for (const callback of this.callbacks) {
64+
callback(NetworkStatus.UNAVAILABLE);
65+
}
66+
}
67+
}

packages/firestore/src/platform_browser/browser_platform.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import { DatabaseId, DatabaseInfo } from '../core/database_info';
1919
import { Platform } from '../platform/platform';
2020
import { Connection } from '../remote/connection';
2121
import { JsonProtoSerializer } from '../remote/serializer';
22+
import { ConnectivityMonitor } from './../remote/connectivity_monitor';
2223

24+
import { BrowserConnectivityMonitor } from './browser_connectivity_monitor';
2325
import { WebChannelConnection } from './webchannel_connection';
2426

2527
export class BrowserPlatform implements Platform {
@@ -43,6 +45,10 @@ export class BrowserPlatform implements Platform {
4345
return Promise.resolve(new WebChannelConnection(databaseInfo));
4446
}
4547

48+
newConnectivityMonitor(): ConnectivityMonitor {
49+
return new BrowserConnectivityMonitor();
50+
}
51+
4652
newSerializer(databaseId: DatabaseId): JsonProtoSerializer {
4753
return new JsonProtoSerializer(databaseId, { useProto3Json: true });
4854
}

packages/firestore/src/platform_node/node_platform.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import { Platform } from '../platform/platform';
2222
import { Connection } from '../remote/connection';
2323
import { JsonProtoSerializer } from '../remote/serializer';
2424
import { Code, FirestoreError } from '../util/error';
25+
import { ConnectivityMonitor } from './../remote/connectivity_monitor';
26+
import { NoopConnectivityMonitor } from './../remote/connectivity_monitor_noop';
2527

2628
import { GrpcConnection } from './grpc_connection';
2729
import { loadProtos } from './load_protos';
@@ -46,6 +48,10 @@ export class NodePlatform implements Platform {
4648
return Promise.resolve(new GrpcConnection(protos, databaseInfo));
4749
}
4850

51+
newConnectivityMonitor(): ConnectivityMonitor {
52+
return new NoopConnectivityMonitor();
53+
}
54+
4955
newSerializer(partitionId: DatabaseId): JsonProtoSerializer {
5056
return new JsonProtoSerializer(partitionId, { useProto3Json: false });
5157
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* The set of network states is deliberately simplified -- we only care about
20+
* states such that transition between them should break currently
21+
* established connections.
22+
*/
23+
export const enum NetworkStatus {
24+
AVAILABLE,
25+
UNAVAILABLE
26+
}
27+
28+
export type ConnectivityMonitorCallback = (status: NetworkStatus) => void;
29+
30+
/**
31+
* A base class for monitoring changes in network connectivity; it is expected
32+
* that each platform will have its own system-dependent implementation.
33+
*/
34+
export interface ConnectivityMonitor {
35+
/**
36+
* Adds a callback to be called when connectivity changes.
37+
*
38+
* Callbacks are not made on the initial state of connectivity, since this
39+
* monitor is primarily used for resetting backoff in the remote store when
40+
* connectivity changes. As such, the initial connectivity state is
41+
* irrelevant here.
42+
*/
43+
addCallback(callback: ConnectivityMonitorCallback): void;
44+
45+
/**
46+
* Stops monitoring connectivity. After this call completes, no further
47+
* callbacks will be triggered. After shutdown() is called, no further calls
48+
* are allowed on this instance.
49+
*/
50+
shutdown(): void;
51+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* @license
3+
* Copyright 2019 Google Inc.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
import { ConnectivityMonitor, NetworkStatus } from './connectivity_monitor';
19+
20+
export class NoopConnectivityMonitor implements ConnectivityMonitor {
21+
addCallback(callback: (status: NetworkStatus) => void): void {
22+
// No-op.
23+
}
24+
25+
shutdown(): void {
26+
// No-op.
27+
}
28+
}

packages/firestore/test/util/test_platform.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import { Platform } from '../../src/platform/platform';
2121
import { Connection } from '../../src/remote/connection';
2222
import { JsonProtoSerializer } from '../../src/remote/serializer';
2323
import { assert, fail } from '../../src/util/assert';
24+
import { ConnectivityMonitor } from './../../src/remote/connectivity_monitor';
25+
import { NoopConnectivityMonitor } from './../../src/remote/connectivity_monitor_noop';
2426

2527
/**
2628
* `Window` fake that implements the event and storage API that is used by
@@ -245,6 +247,10 @@ export class TestPlatform implements Platform {
245247
return this.basePlatform.loadConnection(databaseInfo);
246248
}
247249

250+
newConnectivityMonitor(): ConnectivityMonitor {
251+
return new NoopConnectivityMonitor();
252+
}
253+
248254
newSerializer(databaseId: DatabaseId): JsonProtoSerializer {
249255
return this.basePlatform.newSerializer(databaseId);
250256
}

0 commit comments

Comments
 (0)