Skip to content

Commit ef4879d

Browse files
committed
update
1 parent 19877a2 commit ef4879d

File tree

8 files changed

+66
-58
lines changed

8 files changed

+66
-58
lines changed

lib/optimizely/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import {
4141
} from '../shared_types';
4242
import { newErrorDecision } from '../optimizely_decision';
4343
import OptimizelyUserContext from '../optimizely_user_context';
44-
// import { createProjectConfigManager, ProjectConfigManager } from '../core/project_config/project_config_manager';
4544
import { ProjectConfigManager } from '../project_config/project_config_manager';
4645
import { createDecisionService, DecisionService, DecisionObj } from '../core/decision_service';
4746
import { getImpressionEvent, getConversionEvent } from '../core/event_builder';
@@ -188,8 +187,8 @@ export default class Optimizely implements Client {
188187
* Returns the project configuration retrieved from projectConfigManager
189188
* @return {projectConfig.ProjectConfig}
190189
*/
191-
getProjectConfig(): projectConfig.ProjectConfig | undefined {
192-
return this.projectConfigManager.getConfig();
190+
getProjectConfig(): projectConfig.ProjectConfig | null {
191+
return this.projectConfigManager.getConfig() || null;
193192
}
194193

195194
/**

lib/project_config/config_manager_factory.node.spec.ts

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ vi.mock('../utils/http_request_handler/node_request_handler', () => {
2727
return { NodeRequestHandler };
2828
});
2929

30-
import { getPollingConfigManager, PollingConfigManagerConfig, PollingConfigManagerFactoryOptions } from './config_manager_factory';
30+
import { getPollingConfigManager, PollingConfigManagerConfig } from './config_manager_factory';
3131
import { createPollingProjectConfigManager } from './config_manager_factory.node';
3232
import { NodeRequestHandler } from '../utils/http_request_handler/node_request_handler';
3333
import { DEFAULT_AUTHENTICATED_URL_TEMPLATE, DEFAULT_URL_TEMPLATE } from './constant';
@@ -68,25 +68,6 @@ describe('createPollingConfigManager', () => {
6868
expect(mockGetPollingConfigManager.mock.calls[0][0].autoUpdate).toBe(true);
6969
});
7070

71-
it('uses the default urlTemplate if datafileAccessToken is not provided', () => {
72-
const config = {
73-
sdkKey: 'sdkKey',
74-
};
75-
76-
const projectConfigManager = createPollingProjectConfigManager(config);
77-
expect(mockGetPollingConfigManager.mock.calls[0][0].urlTemplate).toBe(DEFAULT_URL_TEMPLATE);
78-
});
79-
80-
it('uses the default authenticated urlTemplate if datafileAccessToken is provided', () => {
81-
const config = {
82-
sdkKey: 'sdkKey',
83-
datafileAccessToken: 'datafileAccessToken',
84-
};
85-
86-
const projectConfigManager = createPollingProjectConfigManager(config);
87-
expect(mockGetPollingConfigManager.mock.calls[0][0].urlTemplate).toBe(DEFAULT_AUTHENTICATED_URL_TEMPLATE);
88-
});
89-
9071
it('uses the provided options', () => {
9172
const config: PollingConfigManagerConfig = {
9273
datafile: '{}',

lib/project_config/config_manager_factory.node.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ export const createPollingProjectConfigManager = (config: PollingConfigManagerCo
2323
const defaultConfig = {
2424
autoUpdate: true,
2525
requestHandler: new NodeRequestHandler(),
26-
urlTemplate: config.datafileAccessToken ? DEFAULT_AUTHENTICATED_URL_TEMPLATE : DEFAULT_URL_TEMPLATE,
2726
};
2827
return getPollingConfigManager({ ...defaultConfig, ...config });
2928
};

lib/project_config/polling_datafile_manager.spec.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { getMockRepeater } from '../tests/mock/mock_repeater';
2020
import { getMockAbortableRequest, getMockRequestHandler } from '../tests/mock/mock_request_handler';
2121
import PersistentKeyValueCache from '../../lib/plugins/key_value_cache/persistentKeyValueCache';
2222
import { getMockLogger } from '../tests/mock/mock_logger';
23-
import { DEFAULT_URL_TEMPLATE, MIN_UPDATE_INTERVAL, UPDATE_INTERVAL_BELOW_MINIMUM_MESSAGE } from './constant';
23+
import { DEFAULT_AUTHENTICATED_URL_TEMPLATE, DEFAULT_URL_TEMPLATE, MIN_UPDATE_INTERVAL, UPDATE_INTERVAL_BELOW_MINIMUM_MESSAGE } from './constant';
2424
import { resolvablePromise } from '../utils/promise/resolvablePromise';
2525
import { ServiceState } from '../service';
2626
import exp from 'constants';
@@ -748,7 +748,7 @@ describe('PollingDatafileManager', () => {
748748
expect(requestHandler.makeRequest.mock.calls[0][0]).toBe('https://example.com/datafile?key=keyThatExists');
749749
});
750750

751-
it('uses the default urlTemplate if none is provided', async () => {
751+
it('uses the default urlTemplate if none is provided and datafileAccessToken is also not provided', async () => {
752752
const repeater = getMockRepeater();
753753
const requestHandler = getMockRequestHandler();
754754
const mockResponse = getMockAbortableRequest(Promise.resolve({ statusCode: 200, body: '{"foo": "bar"}', headers: {} }));
@@ -768,6 +768,27 @@ describe('PollingDatafileManager', () => {
768768
expect(requestHandler.makeRequest.mock.calls[0][0]).toBe(DEFAULT_URL_TEMPLATE.replace('%s', 'keyThatExists'));
769769
});
770770

771+
it('uses the default authenticated urlTemplate if none is provided and datafileAccessToken is provided', async () => {
772+
const repeater = getMockRepeater();
773+
const requestHandler = getMockRequestHandler();
774+
const mockResponse = getMockAbortableRequest(Promise.resolve({ statusCode: 200, body: '{"foo": "bar"}', headers: {} }));
775+
requestHandler.makeRequest.mockReturnValueOnce(mockResponse);
776+
777+
const manager = new PollingDatafileManager({
778+
repeater,
779+
requestHandler,
780+
sdkKey: 'keyThatExists',
781+
datafileAccessToken: 'token123',
782+
});
783+
784+
manager.start();
785+
repeater.execute(0);
786+
787+
await expect(manager.onRunning()).resolves.not.toThrow();
788+
expect(requestHandler.makeRequest).toHaveBeenCalledOnce();
789+
expect(requestHandler.makeRequest.mock.calls[0][0]).toBe(DEFAULT_AUTHENTICATED_URL_TEMPLATE.replace('%s', 'keyThatExists'));
790+
});
791+
771792
it('returns the datafile from get', async () => {
772793
const repeater = getMockRepeater();
773794
const requestHandler = getMockRequestHandler();

lib/project_config/polling_datafile_manager.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,14 @@ import { LoggerFacade } from '../modules/logging';
1818
import { sprintf } from '../utils/fns';
1919
import { DatafileManager, DatafileManagerConfig } from './datafile_manager';
2020
import { EventEmitter } from '../utils/event_emitter/event_emitter';
21-
import { DEFAULT_URL_TEMPLATE, MIN_UPDATE_INTERVAL, UPDATE_INTERVAL_BELOW_MINIMUM_MESSAGE } from './constant';
21+
import { DEFAULT_AUTHENTICATED_URL_TEMPLATE, DEFAULT_URL_TEMPLATE, MIN_UPDATE_INTERVAL, UPDATE_INTERVAL_BELOW_MINIMUM_MESSAGE } from './constant';
2222
import PersistentKeyValueCache from '../plugins/key_value_cache/persistentKeyValueCache';
2323

2424
import { BaseService, ServiceState } from '../service';
2525
import { RequestHandler, AbortableRequest, Headers, Response } from '../utils/http_request_handler/http';
2626
import { Repeater } from '../utils/repeater/repeater';
2727
import { Consumer, Fn } from '../utils/type';
28+
import { url } from 'inspector';
2829

2930
function isSuccessStatusCode(statusCode: number): boolean {
3031
return statusCode >= 200 && statusCode < 400;
@@ -54,7 +55,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
5455
autoUpdate = false,
5556
sdkKey,
5657
datafileAccessToken,
57-
urlTemplate = DEFAULT_URL_TEMPLATE,
58+
urlTemplate,
5859
cache,
5960
initRetry,
6061
repeater,
@@ -67,13 +68,16 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
6768
this.sdkKey = sdkKey;
6869
this.datafileAccessToken = datafileAccessToken;
6970
this.requestHandler = requestHandler;
70-
this.datafileUrl = sprintf(urlTemplate, this.sdkKey);
7171
this.emitter = new EventEmitter();
7272
this.autoUpdate = autoUpdate;
7373
this.initRetryRemaining = initRetry;
7474
this.repeater = repeater;
7575
this.updateInterval = updateInterval;
7676
this.logger = logger;
77+
78+
const urlTemplateToUse = urlTemplate ||
79+
(datafileAccessToken ? DEFAULT_AUTHENTICATED_URL_TEMPLATE : DEFAULT_URL_TEMPLATE);
80+
this.datafileUrl = sprintf(urlTemplateToUse, this.sdkKey);
7781
}
7882

7983
setLogger(logger: LoggerFacade): void {
@@ -178,7 +182,7 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
178182
}
179183
}
180184

181-
private async syncDatafile(): Promise<void> {
185+
private makeDatafileRequest(): AbortableRequest {
182186
const headers: Headers = {};
183187
if (this.lastResponseLastModified) {
184188
headers['if-modified-since'] = this.lastResponseLastModified;
@@ -190,8 +194,11 @@ export class PollingDatafileManager extends BaseService implements DatafileManag
190194
}
191195

192196
this.logger?.debug('Making datafile request to url %s with headers: %s', this.datafileUrl, () => JSON.stringify(headers));
193-
this.currentRequest = this.requestHandler.makeRequest(this.datafileUrl, headers, 'GET');
197+
return this.requestHandler.makeRequest(this.datafileUrl, headers, 'GET');
198+
}
194199

200+
private async syncDatafile(): Promise<void> {
201+
this.currentRequest = this.makeDatafileRequest();
195202
return this.currentRequest.responsePromise
196203
.then(this.onRequestResolved.bind(this), this.onRequestRejected.bind(this))
197204
.finally(() => this.currentRequest = undefined);

lib/shared_types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ export interface Client {
377377
onReady(options?: { timeout?: number }): Promise<unknown>;
378378
close(): Promise<{ success: boolean; reason?: string }>;
379379
sendOdpEvent(action: string, type?: string, identifiers?: Map<string, string>, data?: Map<string, unknown>): void;
380-
getProjectConfig(): ProjectConfig | undefined;
380+
getProjectConfig(): ProjectConfig | null;
381381
isOdpIntegrated(): boolean;
382382
}
383383

lib/utils/repeater/repeater.spec.ts

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ describe("ExponentialBackoff", () => {
8989
});
9090

9191

92-
describe("IntervalTicker", () => {
92+
describe("IntervalRepeater", () => {
9393
beforeEach(() => {
9494
vi.useFakeTimers();
9595
});
@@ -101,10 +101,10 @@ describe("IntervalTicker", () => {
101101
it('should call the handler at the specified interval', async() => {
102102
const handler = vi.fn().mockResolvedValue(undefined);
103103

104-
const intervalTicker = new IntervalRepeater(2000);
105-
intervalTicker.setTask(handler);
104+
const intervalRepeater = new IntervalRepeater(2000);
105+
intervalRepeater.setTask(handler);
106106

107-
intervalTicker.start();
107+
intervalRepeater.start();
108108

109109
await advanceTimersByTime(2000);
110110
expect(handler).toHaveBeenCalledTimes(1);
@@ -122,10 +122,10 @@ describe("IntervalTicker", () => {
122122
.mockRejectedValueOnce(new Error())
123123
.mockResolvedValueOnce(undefined);
124124

125-
const intervalTicker = new IntervalRepeater(2000);
126-
intervalTicker.setTask(handler);
125+
const intervalRepeater = new IntervalRepeater(2000);
126+
intervalRepeater.setTask(handler);
127127

128-
intervalTicker.start();
128+
intervalRepeater.start();
129129

130130
await advanceTimersByTime(2000);
131131
expect(handler).toHaveBeenCalledTimes(1);
@@ -160,10 +160,10 @@ describe("IntervalTicker", () => {
160160
reset: vi.fn(),
161161
};
162162

163-
const intervalTicker = new IntervalRepeater(30000, backoffController);
164-
intervalTicker.setTask(handler);
163+
const intervalRepeater = new IntervalRepeater(30000, backoffController);
164+
intervalRepeater.setTask(handler);
165165

166-
intervalTicker.start();
166+
intervalRepeater.start();
167167

168168
await advanceTimersByTime(30000);
169169
expect(handler).toHaveBeenCalledTimes(1);
@@ -181,10 +181,10 @@ describe("IntervalTicker", () => {
181181
it('should use the regular interval when the handler fails if backoffController is not provided', async() => {
182182
const handler = vi.fn().mockRejectedValue(new Error());
183183

184-
const intervalTicker = new IntervalRepeater(30000);
185-
intervalTicker.setTask(handler);
184+
const intervalRepeater = new IntervalRepeater(30000);
185+
intervalRepeater.setTask(handler);
186186

187-
intervalTicker.start();
187+
intervalRepeater.start();
188188

189189
await advanceTimersByTime(30000);
190190
expect(handler).toHaveBeenCalledTimes(1);
@@ -207,10 +207,10 @@ describe("IntervalTicker", () => {
207207
reset: vi.fn(),
208208
};
209209

210-
const intervalTicker = new IntervalRepeater(30000, backoffController);
211-
intervalTicker.setTask(handler);
210+
const intervalRepeater = new IntervalRepeater(30000, backoffController);
211+
intervalRepeater.setTask(handler);
212212

213-
intervalTicker.start();
213+
intervalRepeater.start();
214214

215215
await advanceTimersByTime(30000);
216216
expect(handler).toHaveBeenCalledTimes(1);
@@ -237,10 +237,10 @@ describe("IntervalTicker", () => {
237237
const ret = resolvablePromise();
238238
const handler = vi.fn().mockReturnValue(ret);
239239

240-
const intervalTicker = new IntervalRepeater(2000);
241-
intervalTicker.setTask(handler);
240+
const intervalRepeater = new IntervalRepeater(2000);
241+
intervalRepeater.setTask(handler);
242242

243-
intervalTicker.start();
243+
intervalRepeater.start();
244244

245245
await advanceTimersByTime(2000);
246246
expect(handler).toHaveBeenCalledTimes(1);
@@ -264,15 +264,15 @@ describe("IntervalTicker", () => {
264264
const ret = resolvablePromise();
265265
const handler = vi.fn().mockReturnValue(ret);
266266

267-
const intervalTicker = new IntervalRepeater(2000);
268-
intervalTicker.setTask(handler);
267+
const intervalRepeater = new IntervalRepeater(2000);
268+
intervalRepeater.setTask(handler);
269269

270-
intervalTicker.start();
270+
intervalRepeater.start();
271271

272272
await advanceTimersByTime(2000);
273273
expect(handler).toHaveBeenCalledTimes(1);
274274

275-
intervalTicker.stop();
275+
intervalRepeater.stop();
276276

277277
ret.resolve(undefined);
278278
await ret.promise;

lib/utils/repeater/repeater.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ export class IntervalRepeater implements Repeater {
9797
if (!this.isRunning){
9898
return;
9999
}
100-
this.timeoutId = setTimeout(this.executeHandler.bind(this), timeout);
100+
this.timeoutId = setTimeout(this.executeTask.bind(this), timeout);
101101
}
102102

103-
private executeHandler() {
103+
private executeTask() {
104104
if (!this.task) {
105105
return;
106106
}
@@ -113,7 +113,7 @@ export class IntervalRepeater implements Repeater {
113113
start(immediateExecution?: boolean): void {
114114
this.isRunning = true;
115115
if(immediateExecution) {
116-
scheduleMicrotask(this.executeHandler.bind(this));
116+
scheduleMicrotask(this.executeTask.bind(this));
117117
} else {
118118
this.setTimer(this.interval);
119119
}
@@ -125,6 +125,7 @@ export class IntervalRepeater implements Repeater {
125125
}
126126

127127
reset(): void {
128+
this.failureCount = 0;
128129
this.backoffController?.reset();
129130
this.stop();
130131
}

0 commit comments

Comments
 (0)