Skip to content

Commit dbf1d83

Browse files
committed
[FSSDK-11492] make public promise rejection messages non tree-shakable
1 parent a62fdc6 commit dbf1d83

File tree

10 files changed

+76
-48
lines changed

10 files changed

+76
-48
lines changed

lib/event_processor/batch_event_processor.ts

Lines changed: 9 additions & 5 deletions
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

Lines changed: 5 additions & 3 deletions
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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -89,25 +89,16 @@ export const REQUEST_TIMEOUT = 'Request timeout';
8989
export const REQUEST_ERROR = 'Request error';
9090
export const NO_STATUS_CODE_IN_RESPONSE = 'No status code in response';
9191
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';
9792
export const RETRY_CANCELLED = 'Retry cancelled';
98-
export const SERVICE_STOPPED_BEFORE_RUNNING = 'Service stopped before running';
9993
export const ONLY_POST_REQUESTS_ARE_SUPPORTED = 'Only POST requests are supported';
10094
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';
95+
export const FAILED_TO_DISPATCH_EVENTS = 'Failed to dispatch events, status: %s';
10596
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';
10797
export const UNABLE_TO_ATTACH_UNLOAD = 'unable to bind optimizely.close() to page unload event: "%s"';
10898
export const UNABLE_TO_PARSE_AND_SKIPPED_HEADER = 'Unable to parse & skipped header item';
10999
export const CMAB_FETCH_FAILED = 'CMAB decision fetch failed with status: %s';
110100
export const INVALID_CMAB_FETCH_RESPONSE = 'Invalid CMAB fetch response';
111101
export const PROMISE_NOT_ALLOWED = "Promise value is not allowed in sync operation";
102+
export const SERVICE_NOT_RUNNING = "%s not running";
112103

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

lib/odp/event_manager/odp_event_manager.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,13 @@ import {
3030
ODP_EVENT_MANAGER_IS_NOT_RUNNING,
3131
ODP_EVENTS_SHOULD_HAVE_ATLEAST_ONE_KEY_VALUE,
3232
ODP_NOT_INTEGRATED,
33-
FAILED_TO_DISPATCH_EVENTS_WITH_ARG,
33+
FAILED_TO_DISPATCH_EVENTS,
3434
ODP_EVENT_MANAGER_STOPPED
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();

lib/odp/odp_manager.ts

Lines changed: 5 additions & 3 deletions
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.ts

Lines changed: 13 additions & 7 deletions
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

Lines changed: 8 additions & 4 deletions
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

Lines changed: 4 additions & 4 deletions
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 () => {

lib/project_config/project_config_manager.ts

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,16 @@ import { scheduleMicrotask } from '../utils/microtask';
2222
import { Service, ServiceState, BaseService } from '../service';
2323
import { Consumer, Fn, Transformer } from '../utils/type';
2424
import { EventEmitter } from '../utils/event_emitter/event_emitter';
25-
import { DATAFILE_MANAGER_STOPPED, NO_SDKKEY_OR_DATAFILE, DATAFILE_MANAGER_FAILED_TO_START } from 'error_message';
26-
import { OptimizelyError } from '../error/optimizly_error';
2725

26+
import {
27+
SERVICE_FAILED_TO_START,
28+
SERVICE_STOPPED_BEFORE_RUNNING,
29+
} from '../service'
30+
31+
export const NO_SDKKEY_OR_DATAFILE = 'sdkKey or datafile must be provided';
32+
export const GOT_INVALID_DATAFILE = 'got invalid datafile';
33+
34+
import { sprintf } from '../utils/fns';
2835
interface ProjectConfigManagerConfig {
2936
datafile?: string | Record<string, unknown>;
3037
jsonSchemaValidator?: Transformer<unknown, boolean>,
@@ -82,7 +89,7 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf
8289
this.state = ServiceState.Starting;
8390

8491
if (!this.datafile && !this.datafileManager) {
85-
this.handleInitError(new OptimizelyError(NO_SDKKEY_OR_DATAFILE));
92+
this.handleInitError(new Error(NO_SDKKEY_OR_DATAFILE));
8693
return;
8794
}
8895

@@ -119,14 +126,16 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf
119126
}
120127

121128
private handleDatafileManagerError(err: Error): void {
122-
this.logger?.error(DATAFILE_MANAGER_FAILED_TO_START, err);
129+
this.logger?.error(SERVICE_FAILED_TO_START, 'DatafileManager', err.message);
123130

124131
// If datafile manager onRunning() promise is rejected, and the project config manager
125132
// is still in starting state, that means a datafile was not provided in cofig or was invalid,
126133
// otherwise the state would have already been set to running synchronously.
127134
// In this case, we cannot recover.
128135
if (this.isStarting()) {
129-
this.handleInitError(err);
136+
this.handleInitError(new Error(
137+
sprintf(SERVICE_FAILED_TO_START, 'DatafileManager', err.message)
138+
));
130139
}
131140
}
132141

@@ -173,7 +182,7 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf
173182
const fatalError = (this.isStarting() && !this.datafileManager) ||
174183
(this.isStarting() && !fromConfig);
175184
if (fatalError) {
176-
this.handleInitError(err);
185+
this.handleInitError(new Error(GOT_INVALID_DATAFILE));
177186
}
178187
}
179188
}
@@ -206,7 +215,9 @@ export class ProjectConfigManagerImpl extends BaseService implements ProjectConf
206215
}
207216

208217
if (this.isNew() || this.isStarting()) {
209-
this.startPromise.reject(new OptimizelyError(DATAFILE_MANAGER_STOPPED));
218+
this.startPromise.reject(new Error(
219+
sprintf(SERVICE_STOPPED_BEFORE_RUNNING, 'ProjectConfigManager')
220+
));
210221
}
211222

212223
this.state = ServiceState.Stopping;

lib/service.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,7 @@ export abstract class BaseService implements Service {
130130

131131
abstract stop(): void;
132132
}
133+
134+
135+
export const SERVICE_FAILED_TO_START = '%s failed to start, reason: %s';
136+
export const SERVICE_STOPPED_BEFORE_RUNNING = '%s stopped before running';

0 commit comments

Comments
 (0)