E57C feat(firestore, web): expose `webExperimentalForceLongPolling`, `webE… · firebase/flutterfire@6ec2a10 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6ec2a10

Browse files
SelaseKayjude.kwashie
andauthored
feat(firestore, web): expose webExperimentalForceLongPolling, webExperimentalAutoDetectLongPolling and timeoutSeconds on web (#13201)
* fix(firestore): expose on FireStoreSettings * fix(firestore): expose on FireStoreSettings * fix(firestore): change experimentalForceLongPolling to webExperimentalForceLongPolling since it applies to web only. * feat(firestore, web): expose (webExperimentalAutoDetectLongPolling, webExperimentalForceLongPolling, timeoutSeconds) * correct variable name * abstract timeoutDuration within an object * remove description on webExperimentalLongPollingOptions field * resolve documentation * fix analyzer issues * test(firestore, web): add e2e tests for long polling fields * test(firestore, web): add e2e tests for long polling fields * remove skip field from test * remove unused import * tests(firestore,web): make adjustments long polling tests * tests(firestore,web): make adjustments long polling tests --------- Co-authored-by: jude.kwashie <jude.kwashie@hubtel.com>
1 parent 13bb65f commit 6ec2a10

File tree

14 files changed

+229
-13
lines changed

14 files changed

+229
-13
lines changed

packages/cloud_firestore/cloud_firestore/example/integration_test/e2e_test.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import 'instance_e2e.dart';
1818
import 'load_bundle_e2e.dart';
1919
import 'query_e2e.dart';
2020
import 'second_database.dart';
21+
import 'settings_e2e.dart';
2122
import 'snapshot_metadata_e2e.dart';
2223
import 'timestamp_e2e.dart';
2324
import 'transaction_e2e.dart';
@@ -57,5 +58,8 @@ void main() {
5758
if (defaultTargetPlatform != TargetPlatform.windows) {
5859
runSecondDatabaseTests();
5960
}
61+
if (kIsWeb) {
62+
runSettingsTest();
63+
}
6064
});
6165
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2020, the Chromium project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
import 'package:cloud_firestore/cloud_firestore.dart';
6+
import 'package:flutter_test/flutter_test.dart';
7+
8+
void runSettingsTest() {
9+
group(
10+
'$Settings',
11+
() {
12+
late FirebaseFirestore firestore;
13+
14+
setUpAll(() async {
15+
firestore = FirebaseFirestore.instance;
16+
});
17+
18+
Future<Settings> initializeTest() async {
19+
Settings firestoreSettings = const Settings(
20+
persistenceEnabled: false,
21+
webExperimentalForceLongPolling: true,
22+
webExperimentalAutoDetectLongPolling: true,
23+
webExperimentalLongPollingOptions: WebExperimentalLongPollingOptions(
24+
timeoutDuration: Duration(seconds: 15),
25+
),
26+
);
27+
28+
return firestore.settings = firestoreSettings;
29+
}
30+
31+
testWidgets('checks if long polling settings were applied', (_) async {
32+
Settings settings = await initializeTest();
33+
34+
expect(settings.webExperimentalForceLongPolling, true);
35+
36+
expect(settings.webExperimentalAutoDetectLongPolling, true);
37+
38+
expect(
39+
settings.webExperimentalLongPollingOptions,
40+
settings.webExperimentalLongPollingOptions,
41+
);
42+
});
43+
},
44+
);
45+
}

packages/cloud_firestore/cloud_firestore/lib/cloud_firestore.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export 'package:cloud_firestore_platform_interface/cloud_firestore_platform_inte
3333
DocumentChangeType,
3434
PersistenceSettings,
3535
Settings,
36+
WebExperimentalLongPollingOptions,
3637
IndexField,
3738
Index,
3839
FieldOverrides,

packages/cloud_firestore/cloud_firestore/lib/src/firestore.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,11 @@ class FirebaseFirestore extends FirebasePluginPlatform {
315315
persistenceEnabled: settings.persistenceEnabled,
316316
host: settings.host,
317317
cacheSizeBytes: settings.cacheSizeBytes,
318+
webExperimentalForceLongPolling: settings.webExperimentalForceLongPolling,
319+
webExperimentalAutoDetectLongPolling:
320+
settings.webExperimentalAutoDetectLongPolling,
321+
webExperimentalLongPollingOptions:
322+
settings.webExperimentalLongPollingOptions,
318323
);
319324
}
320325

packages/cloud_firestore/cloud_firestore_platform_interface/lib/src/settings.dart

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class Settings {
1616
this.host,
1717
this.sslEnabled,
1818
this.cacheSizeBytes,
19+
this.webExperimentalForceLongPolling,
20+
this.webExperimentalAutoDetectLongPolling,
21+
this.webExperimentalLongPollingOptions,
1922
this.ignoreUndefinedProperties = false,
2023
});
2124

@@ -51,13 +54,39 @@ class Settings {
5154
/// Web only.
5255
final bool ignoreUndefinedProperties;
5356

57+
/// Forces the SDK’s underlying network transport (WebChannel) to use long-polling.
58+
///
59+
/// Each response from the backend will be closed immediately after the backend sends data
60+
/// (by default responses are kept open in case the backend has more data to send).
61+
/// This avoids incompatibility issues with certain proxies, antivirus software, etc.
62+
/// that incorrectly buffer traffic indefinitely.
63+
/// Use of this option will cause some performance degradation though.
64+
final bool? webExperimentalForceLongPolling;
65+
66+
/// Configures the SDK's underlying transport (WebChannel) to automatically detect if long-polling should be used.
67+
///
68+
///This is very similar to [webExperimentalForceLongPolling], but only uses long-polling if required.
69+
final bool? webExperimentalAutoDetectLongPolling;
70+
71+
/// Options that configure the SDK’s underlying network transport (WebChannel) when long-polling is used.
72+
///
73+
/// These options are only used if experimentalForceLongPolling is true
74+
/// or if [webExperimentalAutoDetectLongPolling] is true and the auto-detection determined that long-polling was needed.
75+
/// Otherwise, these options have no effect.
76+
final WebExperimentalLongPollingOptions? webExperimentalLongPollingOptions;
77+
5478
/// Returns the settings as a [Map]
5579
Map<String, dynamic> get asMap {
5680
return {
5781
'persistenceEnabled': persistenceEnabled,
5882
'host': host,
5983
'sslEnabled': sslEnabled,
6084
'cacheSizeBytes': cacheSizeBytes,
85+
'webExperimentalForceLongPolling': webExperimentalForceLongPolling,
86+
'webExperimentalAutoDetectLongPolling':
87+
webExperimentalAutoDetectLongPolling,
88+
'webExperimentalLongPollingOptions':
89+
webExperimentalLongPollingOptions?.asMap,
6190
if (kIsWeb) 'ignoreUndefinedProperties': ignoreUndefinedProperties,
6291
};
6392
}
@@ -67,7 +96,10 @@ class Settings {
6796
String? host,
6897
bool? sslEnabled,
6998
int? cacheSizeBytes,
99+
bool? webExperimentalForceLongPolling,
100+
bool? webExperimentalAutoDetectLongPolling,
70101
bool? ignoreUndefinedProperties,
102+
WebExperimentalLongPollingOptions? webExperimentalLongPollingOptions,
71103
}) {
72104
assert(
73105
cacheSizeBytes == null ||
@@ -81,6 +113,13 @@ class Settings {
81113
host: host ?? this.host,
82114
sslEnabled: sslEnabled ?? this.sslEnabled,
83115
cacheSizeBytes: cacheSizeBytes ?? this.cacheSizeBytes,
116+
webExperimentalForceLongPolling: webExperimentalForceLongPolling ??
117+
this.webExperimentalForceLongPolling,
118+
webExperimentalAutoDetectLongPolling:
119+
webExperimentalAutoDetectLongPolling ??
120+
this.webExperimentalAutoDetectLongPolling,
121+
webExperimentalLongPollingOptions: webExperimentalLongPollingOptions ??
122+
this.webExperimentalLongPollingOptions,
84123
ignoreUndefinedProperties:
85124
ignoreUndefinedProperties ?? this.ignoreUndefinedProperties,
86125
);
@@ -94,6 +133,12 @@ class Settings {
94133
other.host == host &&
95134
other.sslEnabled == sslEnabled &&
96135
other.cacheSizeBytes == cacheSizeBytes &&
136+
other.webExperimentalForceLongPolling ==
137+
webExperimentalForceLongPolling &&
138+
other.webExperimentalAutoDetectLongPolling ==
139+
webExperimentalAutoDetectLongPolling &&
140+
other.webExperimentalLongPollingOptions ==
141+
webExperimentalLongPollingOptions &&
97142
other.ignoreUndefinedProperties == ignoreUndefinedProperties;
98143

99144
@override
@@ -103,9 +148,46 @@ class Settings {
103148
host,
104149
sslEnabled,
105150
cacheSizeBytes,
151+
webExperimentalForceLongPolling,
152+
webExperimentalAutoDetectLongPolling,
153+
webExperimentalLongPollingOptions,
106154
ignoreUndefinedProperties,
107155
);
108156

109157
@override
110158
String toString() => 'Settings($asMap)';
111159
}
160+
161+
/// Options that configure the SDK’s underlying network transport (WebChannel) when long-polling is used.
162+
@immutable
163+
class WebExperimentalLongPollingOptions {
164+
/// The desired maximum timeout interval, in seconds, to complete a long-polling GET response
165+
///
166+
/// Valid values are between 5 and 30, inclusive.
167+
/// By default, when long-polling is used the "hanging GET" request sent by the client times out after 30 seconds.
168+
/// To request a different timeout from the server, set this setting with the desired timeout.
169+
/// Changing the default timeout may be useful, for example,
170+
/// if the buffering proxy that necessitated enabling long-polling in the first place has a shorter timeout for hanging GET requests,
171+
/// in which case setting the long-polling timeout to a shorter value,
172+
/// such as 25 seconds, may fix prematurely-closed hanging GET requests.
173+
final Duration? timeoutDuration;
174+
175+
const WebExperimentalLongPollingOptions({
176+
this.timeoutDuration,
177+
});
178+
179+
Map<String, dynamic> get asMap {
180+
return {
181+
'timeoutDuration': timeoutDuration?.inSeconds,
182+
};
183+
}
184+
185+
@override
186+
bool operator ==(Object other) =>
187+
other is WebExperimentalLongPollingOptions &&
188+
other.runtimeType == runtimeType &&
189+
other.timeoutDuration == timeoutDuration;
190+
191+
@override
192+
int get hashCode => Object.hash(runtimeType, timeoutDuration);
193+
}

packages/cloud_firestore/cloud_firestore_platform_interface/test/settings_test.dart

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,25 @@ void main() {
1414
persistenceEnabled: true,
1515
host: 'foo bar',
1616
sslEnabled: true,
17+
webExperimentalForceLongPolling: false,
18+
webExperimentalAutoDetectLongPolling: false,
1719
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
20+
webExperimentalLongPollingOptions: WebExperimentalLongPollingOptions(
21+
timeoutDuration: Duration(seconds: 4),
22+
),
1823
),
1924
equals(
2025
const Settings(
2126
persistenceEnabled: true,
2227
host: 'foo bar',
2328
sslEnabled: true,
29+
webExperimentalForceLongPolling: false,
30+
webExperimentalAutoDetectLongPolling: false,
2431
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
32+
webExperimentalLongPollingOptions:
33+
WebExperimentalLongPollingOptions(
34+
timeoutDuration: Duration(seconds: 4),
35+
),
2536
),
2637
),
2738
);
@@ -49,6 +60,11 @@ void main() {
4960
persistenceEnabled: true,
5061
host: 'foo bar',
5162
sslEnabled: true,
63+
webExperimentalAutoDetectLongPolling: false,
64+
webExperimentalForceLongPolling: false,
65+
webExperimentalLongPollingOptions: WebExperimentalLongPollingOptions(
66+
timeoutDuration: Duration(seconds: 4),
67+
),
5268
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
5369
);
5470

@@ -60,21 +76,35 @@ void main() {
6076
'persistenceEnabled': null,
6177
'host': null,
6278
'sslEnabled': null,
63-
'cacheSizeBytes': null
79+
'cacheSizeBytes': null,
80+
'webExperimentalForceLongPolling': null,
81+
'webExperimentalAutoDetectLongPolling': null,
82+
'webExperimentalLongPollingOptions': null,
6483
});
6584

6685
expect(
6786
const Settings(
68-
persistenceEnabled: true,
69-
host: 'foo bar',
70-
sslEnabled: true,
71-
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
72-
).asMap,
87+
persistenceEnabled: true,
88+
host: 'foo bar',
89+
sslEnabled: true,
90+
cacheSizeBytes: Settings.CACHE_SIZE_UNLIMITED,
91+
webExperimentalAutoDetectLongPolling: true,
92+
webExperimentalForceLongPolling: true,
93+
webExperimentalLongPollingOptions:
94+
WebExperimentalLongPollingOptions(
95+
timeoutDuration: Duration(seconds: 4),
96+
)).asMap,
7397
<String, dynamic>{
7498
'persistenceEnabled': true,
7599
'host': 'foo bar',
76100
'sslEnabled': true,
77101
'cacheSizeBytes': Settings.CACHE_SIZE_UNLIMITED,
102+
'webExperimentalForceLongPolling': true,
103+
'webExperimentalAutoDetectLongPolling': true,
104+
'webExperimentalLongPollingOptions':
105+
const WebExperimentalLongPollingOptions(
106+
timeoutDuration: Duration(seconds: 4),
107+
).asMap
78108
});
79109
});
80110

packages/cloud_firestore/cloud_firestore_web/lib/cloud_firestore_web.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,18 +152,33 @@ class FirebaseFirestoreWeb extends FirebaseFirestorePlatform {
152152
));
153153
}
154154

155+
JSAny experimentalLongPollingOptions =
156+
firestore_interop.ExperimentalLongPollingOptions(
157+
timeoutSeconds: firestoreSettings.webExperimentalLongPollingOptions
158+
?.timeoutDuration?.inSeconds.toJS) as JSAny;
159+
155160
if (firestoreSettings.host != null &&
156161
firestoreSettings.sslEnabled != null) {
157162
_interopSettings = firestore_interop.FirestoreSettings(
158163
localCache: localCache,
159164
host: firestoreSettings.host?.toJS,
160165
ssl: firestoreSettings.sslEnabled?.toJS,
166+
experimentalForceLongPolling:
167+
firestoreSettings.webExperimentalForceLongPolling?.toJS,
168+
experimentalAutoDetectLongPolling:
169+
firestoreSettings.webExperimentalAutoDetectLongPolling?.toJS,
170+
experimentalLongPollingOptions: experimentalLongPollingOptions,
161171
ignoreUndefinedProperties:
162172
firestoreSettings.ignoreUndefinedProperties.toJS,
163173
);
164174
} else {
165175
_interopSettings = firestore_interop.FirestoreSettings(
166176
localCache: localCache,
177+
experimentalForceLongPolling:
178+
firestoreSettings.webExperimentalForceLongPolling?.toJS,
179+
experimentalAutoDetectLongPolling:
180+
firestoreSettings.webExperimentalAutoDetectLongPolling?.toJS,
181+
experimentalLongPollingOptions: experimentalLongPollingOptions,
167182
ignoreUndefinedProperties:
168183
firestoreSettings.ignoreUndefinedProperties.toJS,
169184
);

packages/cloud_firestore/cloud_firestore_web/lib/src/interop/firestore_interop.dart

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,9 @@ abstract class FirestoreSettings {
719719
JSString? host,
720720
JSBoolean? ssl,
721721
JSBoolean? ignoreUndefinedProperties,
722+
JSBoolean? experimentalForceLongPolling,
723+
JSBoolean? experimentalAutoDetectLongPolling,
724+
JSAny? experimentalLongPollingOptions,
722725
JSObject localCache,
723726
});
724727
}
@@ -748,6 +751,35 @@ extension FirestoreSettingsExtension on FirestoreSettings {
748751
external set localCache(JSObject u);
749752
}
750753

754+
/// Options that configure the SDK’s underlying network transport (WebChannel) when long-polling is used
755+
/// These options are only used if experimentalForceLongPolling is true
756+
/// or if experimentalAutoDetectLongPolling is true and the auto-detection determined that long-polling was needed.
757+
/// Otherwise, these options have no effect.
758+
@anonymous
759+
@JS()
760+
@staticInterop
761+
abstract class ExperimentalLongPollingOptions {
762+
external factory ExperimentalLongPollingOptions({
763+
JSNumber? timeoutSeconds,
764+
});
765+
}
766+
767+
extension ExperimentalLongPollingOptionsExtension
768+
on ExperimentalLongPollingOptions {
769+
/// The desired maximum timeout interval, in seconds, to complete a long-polling GET response
770+
/// Valid values are between 5 and 30, inclusive.
771+
/// Floating point values are allowed and will be rounded to the nearest millisecond
772+
/// By default, when long-polling is used the "hanging GET" request sent by the client times out after 30 seconds.
773+
/// To request a different timeout from the server, set this setting with the desired timeout.
774+
/// Changing the default timeout may be useful, for example,
775+
/// if the buffering proxy that necessitated enabling long-polling in the first place has a shorter timeout for hanging GET requests,
776+
/// in which case setting the long-polling timeout to a shorter value,
777+
/// such as 25 seconds, may fix prematurely-closed hanging GET requests.
778+
external JSNumber? get timeoutSeconds;
779+
780+
external set timeoutSeconds(JSNumber? v);
781+
}
782+
751783
/// Union type from all supported SDK cache layer.
752784
///
753785
/// [MemoryLocalCache] and [MemoryCacheSettings] are the two only cache types supported by the SDK. Custom implementation is not supported.

packages/firebase_app_check/firebase_app_check/example/ios/Flutter/AppFrameworkInfo.plist

Lines changed: 1 addition & 1 deletion
B72
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,6 @@
2121
<key>CFBundleVersion</key>
2222
<string>1.0</string>
2323
<key>MinimumOSVersion</key>
24-
<string>11.0</string>
24+
<string>12.0</string>
2525
</dict>
2626
</plist>

0 commit comments

Comments
 (0)
0