Skip to content

Commit 12c7eed

Browse files
authored
Make initializePerformance() idempotent (#5278)
1 parent d46d84b commit 12c7eed

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

packages-exp/performance-exp/src/index.test.ts

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@
1616
*/
1717

1818
import { expect } from 'chai';
19-
import { stub } from 'sinon';
2019
import { initializePerformance } from './index';
2120
import { ERROR_FACTORY, ErrorCode } from './utils/errors';
22-
import * as firebase from '@firebase/app-exp';
23-
import { Provider } from '@firebase/component';
2421
import '../test/setup';
22+
import { deleteApp, FirebaseApp, initializeApp } from '@firebase/app-exp';
2523

2624
const fakeFirebaseConfig = {
2725
apiKey: 'api-key',
@@ -33,18 +31,43 @@ const fakeFirebaseConfig = {
3331
appId: '1:111:web:a1234'
3432
};
3533

36-
const fakeFirebaseApp = ({
37-
options: fakeFirebaseConfig
38-
} as unknown) as firebase.FirebaseApp;
39-
4034
describe('Firebase Performance > initializePerformance()', () => {
41-
it('throws if a perf instance has already been created', () => {
42-
stub(firebase, '_getProvider').returns(({
43-
isInitialized: () => true
44-
} as unknown) as Provider<'performance-exp'>);
35+
let app: FirebaseApp;
36+
beforeEach(() => {
37+
app = initializeApp(fakeFirebaseConfig);
38+
});
39+
afterEach(() => {
40+
return deleteApp(app);
41+
});
42+
it('returns same instance if given same (no) params a second time', () => {
43+
const performanceInstance = initializePerformance(app);
44+
expect(initializePerformance(app)).to.equal(performanceInstance);
45+
});
46+
it('returns same instance if given same params a second time', () => {
47+
const performanceInstance = initializePerformance(app, {
48+
dataCollectionEnabled: false
49+
});
50+
expect(
51+
initializePerformance(app, { dataCollectionEnabled: false })
52+
).to.equal(performanceInstance);
53+
});
54+
it('throws if called with params after being called with no params', () => {
55+
initializePerformance(app);
56+
const expectedError = ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);
57+
expect(() =>
58+
initializePerformance(app, { dataCollectionEnabled: false })
59+
).to.throw(expectedError.message);
60+
});
61+
it('throws if called with no params after being called with params', () => {
62+
initializePerformance(app, { instrumentationEnabled: false });
63+
const expectedError = ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);
64+
expect(() => initializePerformance(app)).to.throw(expectedError.message);
65+
});
66+
it('throws if called a second time with different params', () => {
67+
initializePerformance(app, { instrumentationEnabled: true });
4568
const expectedError = ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);
46-
expect(() => initializePerformance(fakeFirebaseApp)).to.throw(
47-
expectedError.message
48-
);
69+
expect(() =>
70+
initializePerformance(app, { instrumentationEnabled: false })
71+
).to.throw(expectedError.message);
4972
});
5073
});

packages-exp/performance-exp/src/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ import {
4545
import { name, version } from '../package.json';
4646
import { Trace } from './resources/trace';
4747
import '@firebase/installations-exp';
48-
import { getModularInstance } from '@firebase/util';
48+
import { deepEqual, getModularInstance } from '@firebase/util';
4949

5050
const DEFAULT_ENTRY_NAME = '[DEFAULT]';
5151

@@ -79,7 +79,13 @@ export function initializePerformance(
7979
// throw if an instance was already created.
8080
// It could happen if initializePerformance() is called more than once, or getPerformance() is called first.
8181
if (provider.isInitialized()) {
82-
throw ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);
82+
const existingInstance = provider.getImmediate();
83+
const initialSettings = provider.getOptions() as PerformanceSettings;
84+
if (deepEqual(initialSettings, settings ?? {})) {
85+
return existingInstance;
86+
} else {
87+
throw ERROR_FACTORY.create(ErrorCode.ALREADY_INITIALIZED);
88+
}
8389
}
8490

8591
const perfInstance = provider.initialize({

packages-exp/performance-exp/src/utils/errors.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ const ERROR_DESCRIPTION_MAP: { readonly [key in ErrorCode]: string } = {
6060
'Custom metric name {$customMetricName} is invalid',
6161
[ErrorCode.INVALID_STRING_MERGER_PARAMETER]:
6262
'Input for String merger is invalid, contact support team to resolve.',
63-
[ErrorCode.ALREADY_INITIALIZED]: 'Performance can only be initialized once.'
63+
[ErrorCode.ALREADY_INITIALIZED]:
64+
'initializePerformance() has already been called with ' +
65+
'different options. To avoid this error, call initializePerformance() with the ' +
66+
'same options as when it was originally called, or call getPerformance() to return the' +
67+
' already initialized instance.'
6468
};
6569

6670
interface ErrorParams {

0 commit comments

Comments
 (0)