Skip to content

Commit 1e38673

Browse files
author
Michael Lehenbauer
committed
Add "experimentalForceLongPolling" option.
1 parent 3c53386 commit 1e38673

File tree

11 files changed

+69
-11
lines changed

11 files changed

+69
-11
lines changed

packages/firebase/index.d.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5853,6 +5853,19 @@ declare namespace firebase.firestore {
58535853
* CACHE_SIZE_UNLIMITED to disable garbage collection.
58545854
*/
58555855
cacheSizeBytes?: number;
5856+
5857+
/**
5858+
* Forces the SDK’s underlying network transport (WebChannel) to use
5859+
* long-polling. Each response from the backend will be closed immediately
5860+
* after the backend sends data (by default responses are kept open in
5861+
* case the backend has more data to send). This avoids incompatibility
5862+
* issues with certain proxies, antivirus software, etc. that incorrectly
5863+
* buffer traffic indefinitely. Use of this option will cause some
5864+
* performance degradation though.
5865+
*
5866+
* This setting may be removed in a future release.
5867+
*/
5868+
experimentalForceLongPolling?: boolean;
58565869
}
58575870

58585871
/**
@@ -7209,14 +7222,14 @@ declare namespace firebase.firestore {
72097222
/**
72107223
* Returns a special value that can be used with `set()` or `update()` that tells
72117224
* the server to increment the field's current value by the given value.
7212-
*
7225+
*
72137226
* If either the operand or the current field value uses floating point precision,
72147227
* all arithmetic follows IEEE 754 semantics. If both values are integers,
72157228
* values outside of JavaScript's safe number range (`Number.MIN_SAFE_INTEGER` to
72167229
* `Number.MAX_SAFE_INTEGER`) are also subject to precision loss. Furthermore,
72177230
* once processed by the Firestore backend, all integer operations are capped
72187231
* between -2^63 and 2^63-1.
7219-
*
7232+
*
72207233
* If the current field value is not of type `number`, or if the field does not
72217234
* yet exist, the transformation sets the field to the given value.
72227235
*

packages/firestore-types/index.d.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,19 @@ export interface Settings {
7676
* CACHE_SIZE_UNLIMITED to disable garbage collection.
7777
*/
7878
cacheSizeBytes?: number;
79+
80+
/**
81+
* Forces the SDK’s underlying network transport (WebChannel) to use
82+
* long-polling. Each response from the backend will be closed immediately
83+
* after the backend sends data (by default responses are kept open in case
84+
* the backend has more data to send). This avoids incompatibility issues
85+
* with certain proxies, antivirus software, etc. that incorrectly buffer
86+
* traffic indefinitely. Use of this option will cause some performance
87+
* degradation though.
88+
*
89+
* This setting may be removed in a future release.
90+
*/
91+
experimentalForceLongPolling?: boolean;
7992
}
8093

8194
/**

packages/firestore/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# Unreleased
2+
- [feature] Added an `experimentalForceLongPolling` setting that may be helpful
3+
to diagnose and avoid connection issues with proxies in certain cases.
24

35
# 1.1.1
46
- [changed] Increased a connection timeout that could lead to large writes

packages/firestore/src/api/database.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ import {
109109
const DEFAULT_HOST = 'firestore.googleapis.com';
110110
const DEFAULT_SSL = true;
111111
const DEFAULT_TIMESTAMPS_IN_SNAPSHOTS = true;
112+
const DEFAULT_FORCE_LONG_POLLING = false;
112113

113114
/**
114115
* Constant used to indicate the LRU garbage collection should be disabled.
@@ -151,6 +152,8 @@ class FirestoreSettings {
151152

152153
readonly cacheSizeBytes: number;
153154

155+
readonly forceLongPolling: boolean;
156+
154157
// Can be a google-auth-library or gapi client.
155158
// tslint:disable-next-line:no-any
156159
credentials?: any;
@@ -177,7 +180,8 @@ class FirestoreSettings {
177180
'ssl',
178181
'credentials',
179182
'timestampsInSnapshots',
180-
'cacheSizeBytes'
183+
'cacheSizeBytes',
184+
'experimentalForceLongPolling'
181185
]);
182186

183187
validateNamedOptionalType(
@@ -253,6 +257,17 @@ class FirestoreSettings {
253257
this.cacheSizeBytes = settings.cacheSizeBytes;
254258
}
255259
}
260+
261+
validateNamedOptionalType(
262+
'settings',
263+
'boolean',
264+
'experimentalForceLongPolling',
265+
settings.experimentalForceLongPolling
266+
);
267+
this.forceLongPolling =
268+
settings.experimentalForceLongPolling === undefined
269+
? DEFAULT_FORCE_LONG_POLLING
270+
: settings.experimentalForceLongPolling;
256271
}
257272

258273
isEqual(other: FirestoreSettings): boolean {
@@ -261,7 +276,8 @@ class FirestoreSettings {
261276
this.ssl === other.ssl &&
262277
this.timestampsInSnapshots === other.timestampsInSnapshots &&
263278
this.credentials === other.credentials &&
264-
this.cacheSizeBytes === other.cacheSizeBytes
279+
this.cacheSizeBytes === other.cacheSizeBytes &&
280+
this.forceLongPolling === other.forceLongPolling
265281
);
266282
}
267283
}
@@ -412,7 +428,8 @@ export class Firestore implements firestore.FirebaseFirestore, FirebaseService {
412428
this._config.databaseId,
413429
this._config.persistenceKey,
414430
this._config.settings.host,
415-
this._config.settings.ssl
431+
this._config.settings.ssl,
432+
this._config.settings.forceLongPolling
416433
);
417434

418435
const preConverter = (value: unknown) => {

packages/firestore/src/core/database_info.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,15 @@ export class DatabaseInfo {
2727
* storage (used in conjunction with the databaseId).
2828
* @param host The Firestore backend host to connect to.
2929
* @param ssl Whether to use SSL when connecting.
30+
* @param forceLongPolling Whether to use the forceLongPolling option
31+
* when using WebChannel as the network transport.
3032
*/
3133
constructor(
3234
readonly databaseId: DatabaseId,
3335
readonly persistenceKey: string,
3436
readonly host: string,
35-
readonly ssl: boolean
37+
readonly ssl: boolean,
38+
readonly forceLongPolling: boolean
3639
) {}
3740
}
3841

packages/firestore/src/platform_browser/webchannel_connection.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,13 @@ const XHR_TIMEOUT_SECS = 15;
6161
export class WebChannelConnection implements Connection {
6262
private readonly databaseId: DatabaseId;
6363
private readonly baseUrl: string;
64+
private readonly forceLongPolling: boolean;
6465

6566
constructor(info: DatabaseInfo) {
6667
this.databaseId = info.databaseId;
6768
const proto = info.ssl ? 'https' : 'http';
6869
this.baseUrl = proto + '://' + info.host;
70+
this.forceLongPolling = info.forceLongPolling;
6971
}
7072

7173
/**
@@ -217,7 +219,8 @@ export class WebChannelConnection implements Connection {
217219
// set it very large (5-10 minutes) and rely on the browser's builtin
218220
// timeouts to kick in if the request isn't working.
219221
forwardChannelRequestTimeoutMs: 10 * 60 * 1000
220-
}
222+
},
223+
forceLongPolling: this.forceLongPolling
221224
};
222225

223226
this.modifyHeadersForRequest(request.initMessageHeaders, token);

packages/firestore/test/integration/browser/webchannel.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ describeFn('WebChannel', () => {
3535
new DatabaseId('testproject'),
3636
'persistenceKey',
3737
'example.com',
38-
false
38+
/*ssl=*/ false,
39+
/*forceLongPolling=*/ false
3940
);
4041
const conn = new WebChannelConnection(info);
4142
const makeUrl = conn.makeUrl.bind(conn);

packages/firestore/test/integration/util/internal_helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ export function getDefaultDatabaseInfo(): DatabaseInfo {
3939
new DatabaseId(DEFAULT_PROJECT_ID),
4040
'persistenceKey',
4141
DEFAULT_SETTINGS.host!,
42-
!!DEFAULT_SETTINGS.ssl
42+
!!DEFAULT_SETTINGS.ssl,
43+
!!DEFAULT_SETTINGS.experimentalForceLongPolling
4344
);
4445
}
4546

packages/firestore/test/unit/local/persistence_test_helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ const TEST_DATABASE_INFO = new DatabaseInfo(
6060
TEST_DATABASE_ID,
6161
'[PersistenceTestHelpers]',
6262
'host',
63-
/*ssl=*/ false
63+
/*ssl=*/ false,
64+
/*forceLongPolling=*/ false
6465
);
6566

6667
/** The persistence prefix used for testing in IndexedBD and LocalStorage. */

packages/firestore/test/unit/specs/spec_test_runner.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,8 @@ abstract class TestRunner {
401401
new DatabaseId('project'),
402402
'persistenceKey',
403403
'host',
404-
false
404+
/*ssl=*/ false,
405+
/*forceLongPolling=*/ false
405406
);
406407

407408
// TODO(mrschmidt): During client startup in `firestore_client`, we block

packages/webchannel-wrapper/externs/overrides.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,6 @@ goog.net.WebChannel.Options.fastHandshake;
6565

6666
/** @type {!Object<string, boolean|number>|undefined} */
6767
goog.net.WebChannel.Options.internalChannelParams;
68+
69+
/** @type {boolean|undefined} */
70+
goog.net.WebChannel.Options.forceLongPolling;

0 commit comments

Comments
 (0)