Skip to content

Commit dd66bea

Browse files
authored
[FSSDK-11492] make public promise rejection messages non tree-shakable (#1041)
1 parent a62fdc6 commit dd66bea

11 files changed

+81
-58
lines changed

lib/event_processor/batch_event_processor.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,10 @@ import { isSuccessStatusCode } from "../utils/http_request_handler/http_util";
2727
import { EventEmitter } from "../utils/event_emitter/event_emitter";
2828
import { IdGenerator } from "../utils/id_generator";
2929
import { areEventContextsEqual } from "./event_builder/user_event";
30-
import { EVENT_PROCESSOR_STOPPED, FAILED_TO_DISPATCH_EVENTS, FAILED_TO_DISPATCH_EVENTS_WITH_ARG } from "error_message";
30+
import { FAILED_TO_DISPATCH_EVENTS, SERVICE_NOT_RUNNING } from "error_message";
3131
import { OptimizelyError } from "../error/optimizly_error";
32+
import { sprintf } from "../utils/fns";
33+
import { SERVICE_STOPPED_BEFORE_RUNNING } from "../service";
3234

3335
export const DEFAULT_MIN_BACKOFF = 1000;
3436
export const DEFAULT_MAX_BACKOFF = 32000;
@@ -174,7 +176,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
174176
const dispatcher = closing && this.closingEventDispatcher ? this.closingEventDispatcher : this.eventDispatcher;
175177
return dispatcher.dispatchEvent(request).then((res) => {
176178
if (res.statusCode && !isSuccessStatusCode(res.statusCode)) {
177-
return Promise.reject(new OptimizelyError(FAILED_TO_DISPATCH_EVENTS_WITH_ARG, res.statusCode));
179+
return Promise.reject(new OptimizelyError(FAILED_TO_DISPATCH_EVENTS, res.statusCode));
178180
}
179181
return Promise.resolve(res);
180182
});
@@ -209,7 +211,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
209211
}).catch((err) => {
210212
// if the dispatch fails, the events will still be
211213
// in the store for future processing
212-
this.logger?.error(FAILED_TO_DISPATCH_EVENTS, err);
214+
this.logger?.error(err);
213215
}).finally(() => {
214216
this.runningTask.delete(taskId);
215217
ids.forEach((id) => this.dispatchingEventIds.delete(id));
@@ -228,7 +230,7 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
228230

229231
async process(event: ProcessableEvent): Promise<void> {
230232
if (!this.isRunning()) {
231-
return Promise.reject('Event processor is not running');
233+
return Promise.reject(new OptimizelyError(SERVICE_NOT_RUNNING, 'BatchEventProcessor'));
232234
}
233235

234236
const eventWithId = {
@@ -285,7 +287,9 @@ export class BatchEventProcessor extends BaseService implements EventProcessor {
285287
}
286288

287289
if (this.isNew()) {
288-
this.startPromise.reject(new OptimizelyError(EVENT_PROCESSOR_STOPPED));
290+
this.startPromise.reject(new Error(
291+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'BatchEventProcessor')
292+
));
289293
}
290294

291295
this.state = ServiceState.Stopping;

lib/event_processor/forwarding_event_processor.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ import { buildLogEvent } from './event_builder/log_event';
2323
import { BaseService, ServiceState } from '../service';
2424
import { EventEmitter } from '../utils/event_emitter/event_emitter';
2525
import { Consumer, Fn } from '../utils/type';
26-
import { SERVICE_STOPPED_BEFORE_RUNNING } from 'error_message';
27-
import { OptimizelyError } from '../error/optimizly_error';
26+
import { SERVICE_STOPPED_BEFORE_RUNNING } from '../service';
27+
import { sprintf } from '../utils/fns';
2828

2929
class ForwardingEventProcessor extends BaseService implements EventProcessor {
3030
private dispatcher: EventDispatcher;
@@ -57,7 +57,9 @@ class ForwardingEventProcessor extends BaseService implements EventProcessor {
5757
}
5858

5959
if (this.isNew()) {
60-
this.startPromise.reject(new OptimizelyError(SERVICE_STOPPED_BEFORE_RUNNING));
60+
this.startPromise.reject(new Error(
61+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'ForwardingEventProcessor'))
62+
);
6163
}
6264

6365
this.state = ServiceState.Terminated;

lib/message/error_message.ts

+2-12
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ export const NO_EVENT_PROCESSOR = 'No event processor is provided';
4141
export const NO_VARIATION_FOR_EXPERIMENT_KEY = 'No variation key %s defined in datafile for experiment %s.';
4242
export const ODP_CONFIG_NOT_AVAILABLE = 'ODP config is not available.';
4343
export const ODP_EVENT_FAILED = 'ODP event send failed.';
44-
export const ODP_EVENT_MANAGER_IS_NOT_RUNNING = 'ODP event manager is not running.';
4544
export const ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE = 'ODP events should have at least one key-value pair in identifiers.';
4645
export const ODP_EVENT_FAILED_ODP_MANAGER_MISSING = 'ODP Event failed to send. (ODP Manager not available).';
4746
export const ODP_NOT_INTEGRATED = 'ODP is not integrated';
@@ -89,25 +88,16 @@ export const REQUEST_TIMEOUT = 'Request timeout';
8988
export const REQUEST_ERROR = 'Request error';
9089
export const NO_STATUS_CODE_IN_RESPONSE = 'No status code in response';
9190
export const UNSUPPORTED_PROTOCOL = 'Unsupported protocol: %s';
92-
export const ONREADY_TIMEOUT = 'onReady timeout expired after %s ms';
93-
export const INSTANCE_CLOSED = 'Instance closed';
94-
export const DATAFILE_MANAGER_STOPPED = 'Datafile manager stopped before it could be started';
95-
export const FAILED_TO_FETCH_DATAFILE = 'Failed to fetch datafile';
96-
export const NO_SDKKEY_OR_DATAFILE = 'At least one of sdkKey or datafile must be provided';
9791
export const RETRY_CANCELLED = 'Retry cancelled';
98-
export const SERVICE_STOPPED_BEFORE_RUNNING = 'Service stopped before running';
9992
export const ONLY_POST_REQUESTS_ARE_SUPPORTED = 'Only POST requests are supported';
10093
export const SEND_BEACON_FAILED = 'sendBeacon failed';
101-
export const FAILED_TO_DISPATCH_EVENTS = 'Failed to dispatch events'
102-
export const FAILED_TO_DISPATCH_EVENTS_WITH_ARG = 'Failed to dispatch events: %s';
103-
export const EVENT_PROCESSOR_STOPPED = 'Event processor stopped before it could be started';
104-
export const ODP_MANAGER_STOPPED_BEFORE_RUNNING = 'odp manager stopped before running';
94+
export const FAILED_TO_DISPATCH_EVENTS = 'Failed to dispatch events, status: %s';
10595
export const ODP_EVENT_MANAGER_STOPPED = "ODP event manager stopped before it could start";
106-
export const DATAFILE_MANAGER_FAILED_TO_START = 'Datafile manager failed to start';
10796
export const UNABLE_TO_ATTACH_UNLOAD = 'unable to bind optimizely.close() to page unload event: "%s"';
10897
export const UNABLE_TO_PARSE_AND_SKIPPED_HEADER = 'Unable to parse & skipped header item';
10998
export const CMAB_FETCH_FAILED = 'CMAB decision fetch failed with status: %s';
11099
export const INVALID_CMAB_FETCH_RESPONSE = 'Invalid CMAB fetch response';
111100
export const PROMISE_NOT_ALLOWED = "Promise value is not allowed in sync operation";
101+
export const SERVICE_NOT_RUNNING = "%s not running";
112102

113103
export const messages: string[] = [];

lib/odp/event_manager/odp_event_manager.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,16 @@ import {
2727
EVENT_ACTION_INVALID,
2828
EVENT_DATA_INVALID,
2929
FAILED_TO_SEND_ODP_EVENTS,
30-
ODP_EVENT_MANAGER_IS_NOT_RUNNING,
3130
ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE,
3231
ODP_NOT_INTEGRATED,
33-
FAILED_TO_DISPATCH_EVENTS_WITH_ARG,
34-
ODP_EVENT_MANAGER_STOPPED
32+
FAILED_TO_DISPATCH_EVENTS,
33+
ODP_EVENT_MANAGER_STOPPED,
34+
SERVICE_NOT_RUNNING
3535
} from 'error_message';
3636
import { OptimizelyError } from '../../error/optimizly_error';
3737
import { LoggerFacade } from '../../logging/logger';
38+
import { SERVICE_STOPPED_BEFORE_RUNNING } from '../../service';
39+
import { sprintf } from '../../utils/fns';
3840

3941
export interface OdpEventManager extends Service {
4042
updateConfig(odpIntegrationConfig: OdpIntegrationConfig): void;
@@ -86,7 +88,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag
8688
private async executeDispatch(odpConfig: OdpConfig, batch: OdpEvent[]): Promise<unknown> {
8789
const res = await this.apiManager.sendEvents(odpConfig, batch);
8890
if (res.statusCode && !isSuccessStatusCode(res.statusCode)) {
89-
return Promise.reject(new OptimizelyError(FAILED_TO_DISPATCH_EVENTS_WITH_ARG, res.statusCode));
91+
return Promise.reject(new OptimizelyError(FAILED_TO_DISPATCH_EVENTS, res.statusCode));
9092
}
9193
return await Promise.resolve(res);
9294
}
@@ -113,7 +115,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag
113115
}
114116

115117
start(): void {
116-
if (!this.isNew) {
118+
if (!this.isNew()) {
117119
return;
118120
}
119121

@@ -164,7 +166,9 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag
164166
}
165167

166168
if (this.isNew()) {
167-
this.startPromise.reject(new OptimizelyError(ODP_EVENT_MANAGER_STOPPED));
169+
this.startPromise.reject(new Error(
170+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'OdpEventManager')
171+
));
168172
}
169173

170174
this.flush();
@@ -174,7 +178,7 @@ export class DefaultOdpEventManager extends BaseService implements OdpEventManag
174178

175179
sendEvent(event: OdpEvent): void {
176180
if (!this.isRunning()) {
177-
this.logger?.error(ODP_EVENT_MANAGER_IS_NOT_RUNNING);
181+
this.logger?.error(SERVICE_NOT_RUNNING, 'OdpEventManager');
178182
return;
179183
}
180184

lib/odp/odp_manager.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ import { CLIENT_VERSION, JAVASCRIPT_CLIENT_ENGINE } from '../utils/enums';
2929
import { ODP_DEFAULT_EVENT_TYPE, ODP_EVENT_ACTION, ODP_USER_KEY } from './constant';
3030
import { isVuid } from '../vuid/vuid';
3131
import { Maybe } from '../utils/type';
32-
import { ODP_MANAGER_STOPPED_BEFORE_RUNNING } from 'error_message';
33-
import { OptimizelyError } from '../error/optimizly_error';
32+
import { sprintf } from '../utils/fns';
33+
import { SERVICE_STOPPED_BEFORE_RUNNING } from '../service';
3434

3535
export interface OdpManager extends Service {
3636
updateConfig(odpIntegrationConfig: OdpIntegrationConfig): boolean;
@@ -151,7 +151,9 @@ export class DefaultOdpManager extends BaseService implements OdpManager {
151151
}
152152

153153
if (!this.isRunning()) {
154-
this.startPromise.reject(new OptimizelyError(ODP_MANAGER_STOPPED_BEFORE_RUNNING));
154+
this.startPromise.reject(new Error(
155+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'OdpManager')
156+
));
155157
}
156158

157159
this.state = ServiceState.Stopping;

lib/optimizely/index.tests.js

+3-5
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ import {
4444
NOT_TRACKING_USER,
4545
EVENT_KEY_NOT_FOUND,
4646
INVALID_EXPERIMENT_KEY,
47-
ONREADY_TIMEOUT,
4847
SERVICE_STOPPED_BEFORE_RUNNING
4948
} from 'error_message';
5049

50+
import { ONREADY_TIMEOUT, INSTANCE_CLOSED } from './';
5151
import {
5252
AUDIENCE_EVALUATION_RESULT_COMBINED,
5353
USER_NOT_IN_EXPERIMENT,
@@ -9455,8 +9455,7 @@ describe('lib/optimizely', function() {
94559455
return readyPromise.then(() => {
94569456
return Promise.reject(new Error('PROMISE_SHOULD_NOT_HAVE_RESOLVED'));
94579457
}, (err) => {
9458-
assert.equal(err.baseMessage, ONREADY_TIMEOUT);
9459-
assert.deepEqual(err.params, [ 500 ]);
9458+
assert.equal(err.message, sprintf(ONREADY_TIMEOUT, 500));
94609459
});
94619460
});
94629461

@@ -9479,8 +9478,7 @@ describe('lib/optimizely', function() {
94799478
return readyPromise.then(() => {
94809479
return Promise.reject(new Error('PROMISE_SHOULD_NOT_HAVE_RESOLVED'));
94819480
}, (err) => {
9482-
assert.equal(err.baseMessage, ONREADY_TIMEOUT);
9483-
assert.deepEqual(err.params, [ 30000 ]);
9481+
assert.equal(err.message, sprintf(ONREADY_TIMEOUT, 30000));
94849482
});
94859483
});
94869484

lib/optimizely/index.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import {
5959
NODE_CLIENT_ENGINE,
6060
CLIENT_VERSION,
6161
} from '../utils/enums';
62-
import { Fn, Maybe, OpType, OpValue } from '../utils/type';
62+
import { Fn, Maybe, OpType } from '../utils/type';
6363
import { resolvablePromise } from '../utils/promise/resolvablePromise';
6464

6565
import { NOTIFICATION_TYPES, DecisionNotificationType, DECISION_NOTIFICATION_TYPES } from '../notification_center/type';
@@ -75,9 +75,6 @@ import {
7575
EVENT_KEY_NOT_FOUND,
7676
NOT_TRACKING_USER,
7777
VARIABLE_REQUESTED_WITH_WRONG_TYPE,
78-
ONREADY_TIMEOUT,
79-
INSTANCE_CLOSED,
80-
SERVICE_STOPPED_BEFORE_RUNNING
8178
} from 'error_message';
8279

8380
import {
@@ -98,6 +95,8 @@ import {
9895
VARIABLE_NOT_USED_RETURN_DEFAULT_VARIABLE_VALUE,
9996
} from 'log_message';
10097

98+
import { SERVICE_STOPPED_BEFORE_RUNNING } from '../service';
99+
101100
import { ErrorNotifier } from '../error/error_notifier';
102101
import { ErrorReporter } from '../error/error_reporter';
103102
import { OptimizelyError } from '../error/optimizly_error';
@@ -113,6 +112,9 @@ type StringInputs = Partial<Record<InputKey, unknown>>;
113112

114113
type DecisionReasons = (string | number)[];
115114

115+
export const INSTANCE_CLOSED = 'Instance closed';
116+
export const ONREADY_TIMEOUT = 'onReady timeout expired after %s ms';
117+
116118
/**
117119
* options required to create optimizely object
118120
*/
@@ -1257,7 +1259,9 @@ export default class Optimizely extends BaseService implements Client {
12571259
}
12581260

12591261
if (!this.isRunning()) {
1260-
this.startPromise.reject(new OptimizelyError(SERVICE_STOPPED_BEFORE_RUNNING));
1262+
this.startPromise.reject(new Error(
1263+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'Client')
1264+
));
12611265
}
12621266

12631267
this.state = ServiceState.Stopping;
@@ -1322,14 +1326,16 @@ export default class Optimizely extends BaseService implements Client {
13221326

13231327
const onReadyTimeout = () => {
13241328
this.cleanupTasks.delete(cleanupTaskId);
1325-
timeoutPromise.reject(new OptimizelyError(ONREADY_TIMEOUT, timeoutValue));
1329+
timeoutPromise.reject(new Error(
1330+
sprintf(ONREADY_TIMEOUT, timeoutValue)
1331+
));
13261332
};
13271333

13281334
const readyTimeout = setTimeout(onReadyTimeout, timeoutValue);
13291335

13301336
this.cleanupTasks.set(cleanupTaskId, () => {
13311337
clearTimeout(readyTimeout);
1332-
timeoutPromise.reject(new OptimizelyError(INSTANCE_CLOSED));
1338+
timeoutPromise.reject(new Error(INSTANCE_CLOSED));
13331339
});
13341340

13351341
return Promise.race([this.onRunning().then(() => {

lib/project_config/polling_datafile_manager.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,8 @@ import { Repeater } from '../utils/repeater/repeater';
2424
import { Consumer, Fn } from '../utils/type';
2525
import { isSuccessStatusCode } from '../utils/http_request_handler/http_util';
2626
import {
27-
DATAFILE_MANAGER_STOPPED,
2827
DATAFILE_FETCH_REQUEST_FAILED,
2928
ERROR_FETCHING_DATAFILE,
30-
FAILED_TO_FETCH_DATAFILE,
3129
} from 'error_message';
3230
import {
3331
ADDING_AUTHORIZATION_HEADER_WITH_BEARER_TOKEN,
@@ -40,6 +38,10 @@ import { LoggerFacade } from '../logging/logger';
4038

4139
export const LOGGER_NAME = 'PollingDatafileManager';
4240

41+
import { SERVICE_STOPPED_BEFORE_RUNNING } from '../service';
42+
43+
export const FAILED_TO_FETCH_DATAFILE = 'Failed to fetch datafile';
44+
4345
export class PollingDatafileManager extends BaseService implements DatafileManager {
4446
private requestHandler: RequestHandler;
4547
private currentDatafile?: string;
@@ -123,7 +125,9 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
123125
}
124126

125127
if (this.isNew() || this.isStarting()) {
126-
this.startPromise.reject(new OptimizelyError(DATAFILE_MANAGER_STOPPED));
128+
this.startPromise.reject(new Error(
129+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'PollingDatafileManager')
130+
));
127131
}
128132

129133
this.state = ServiceState.Terminated;
@@ -136,7 +140,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
136140
private handleInitFailure(): void {
137141
this.state = ServiceState.Failed;
138142
this.repeater.stop();
139-
const error = new OptimizelyError(FAILED_TO_FETCH_DATAFILE);
143+
const error = new Error(FAILED_TO_FETCH_DATAFILE);
140144
this.startPromise.reject(error);
141145
this.stopPromise.reject(error);
142146
}

lib/project_config/project_config_manager.spec.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,10 @@ describe('ProjectConfigManagerImpl', () => {
209209

210210
describe('when datafile is invalid', () => {
211211
it('should reject onRunning() with the same error if datafileManager.onRunning() rejects', async () => {
212-
const datafileManager = getMockDatafileManager({ onRunning: Promise.reject('test error') });
212+
const datafileManager = getMockDatafileManager({ onRunning: Promise.reject(new Error('test error')) });
213213
const manager = new ProjectConfigManagerImpl({ datafile: {}, datafileManager });
214214
manager.start();
215-
await expect(manager.onRunning()).rejects.toBe('test error');
215+
await expect(manager.onRunning()).rejects.toThrow('DatafileManager failed to start, reason: test error');
216216
});
217217

218218
it('should resolve onRunning() if datafileManager.onUpdate() is fired and should update config', async () => {
@@ -258,10 +258,10 @@ describe('ProjectConfigManagerImpl', () => {
258258

259259
describe('when datafile is not provided', () => {
260260
it('should reject onRunning() if datafileManager.onRunning() rejects', async () => {
261-
const datafileManager = getMockDatafileManager({ onRunning: Promise.reject('test error') });
261+
const datafileManager = getMockDatafileManager({ onRunning: Promise.reject(new Error('test error')) });
262262
const manager = new ProjectConfigManagerImpl({ datafileManager });
263263
manager.start();
264-
await expect(manager.onRunning()).rejects.toBe('test error');
264+
await expect(manager.onRunning()).rejects.toThrow('DatafileManager failed to start, reason: test error');
265265
});
266266

267267
it('should reject onRunning() and onTerminated if datafileManager emits an invalid datafile in the first onUpdate', async () => {

0 commit comments

Comments
 (0)