Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[firebase_remote_config] Remote config/double instance error #2061

Closed
wants to merge 11 commits into from
5 changes: 5 additions & 0 deletions packages/firebase_remote_config/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.3.0+4

* Fix `Bad state: Future already completed` error when initially
calling `RemoteConfig.instance` multiple times in parallel.

## 0.3.0+3

* Replace deprecated `getFlutterEngine` call on Android.
Expand Down
14 changes: 10 additions & 4 deletions packages/firebase_remote_config/lib/src/remote_config.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,23 @@ class RemoteConfig extends ChangeNotifier {
RemoteConfigSettings _remoteConfigSettings;

DateTime get lastFetchTime => _lastFetchTime;

LastFetchStatus get lastFetchStatus => _lastFetchStatus;

RemoteConfigSettings get remoteConfigSettings => _remoteConfigSettings;

static Completer<RemoteConfig> _instanceCompleter = Completer<RemoteConfig>();
@visibleForTesting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're generally trying to avoid @VisibleForTesting APIs since they clutter the public logs, though I don't see another solution at this point.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Totally agree, I tried to find an alternative first before using it, but have to change it back somehow...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@FirebaseExtended/invertase @collinjackson is there any other solution to be able to test for this edge case?

static Completer<RemoteConfig> instanceCompleter = Completer<RemoteConfig>();

/// Gets the instance of RemoteConfig for the default Firebase app.
static Future<RemoteConfig> get instance async {
if (!_instanceCompleter.isCompleted) {
_instanceCompleter.complete(await _getRemoteConfigInstance());
if (!instanceCompleter.isCompleted) {
final _remoteConfigInstance = await _getRemoteConfigInstance();
if (!instanceCompleter.isCompleted) {
instanceCompleter.complete(_remoteConfigInstance);
}
}
return _instanceCompleter.future;
return instanceCompleter.future;
}

static Future<RemoteConfig> _getRemoteConfigInstance() async {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:async';

import 'package:firebase_remote_config/firebase_remote_config.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
Expand Down Expand Up @@ -40,6 +42,12 @@ void main() {
});
});

tearDown(() {
RemoteConfig.instanceCompleter = Completer<RemoteConfig>();
// empty log for next tests
log.removeWhere((_) => true);
});

test('instance', () async {
final RemoteConfig remoteConfig = await RemoteConfig.instance;
expect(
Expand All @@ -59,10 +67,12 @@ void main() {
RemoteConfig.instance,
RemoteConfig.instance,
];
Future.wait(futures).then((List<RemoteConfig> remoteConfigs) {
// Check that both returned Remote Config instances are the same.
expect(remoteConfigs[0], remoteConfigs[1]);
});
final List<RemoteConfig> remoteConfigs = await Future.wait(futures);
// Check that both returned Remote Config instances are the same.
expect(remoteConfigs[0], remoteConfigs[1]);
// Check that method RemoteConfig#instance was called at least once
expect(log.length, isPositive);
expect(log[0], isMethodCall('RemoteConfig#instance', arguments: null));
});
});

Expand Down