@autofleet/settings 1.0.5-beta-3 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +34 -42
- package/dist/index.test.js +182 -123
- package/package.json +1 -1
- package/src/index.test.ts +180 -112
- package/src/index.ts +32 -43
package/dist/index.js
CHANGED
|
@@ -29,7 +29,7 @@ const waitingToNetwork = 'waitingToNetwork';
|
|
|
29
29
|
const findUrl = (serviceUrl) => serviceUrl
|
|
30
30
|
|| (process.env.SETTING_MS_SERVICE_HOST && process.env.SETTING_MS_SERVICE_HOST.length > 0 ? `http://${process.env.SETTING_MS_SERVICE_HOST}/` : undefined)
|
|
31
31
|
|| (process.env.NODE_ENV !== 'test' ? 'http://setting-ms.autofleet.io/' : 'http://localhost:9999/');
|
|
32
|
-
class
|
|
32
|
+
class CannotGetNetworkValueError extends Error {
|
|
33
33
|
}
|
|
34
34
|
class SettingsManager {
|
|
35
35
|
constructor({ serviceUrl, ttl = fiveMinutes } = {}) {
|
|
@@ -87,7 +87,7 @@ class SettingsManager {
|
|
|
87
87
|
catch (error) {
|
|
88
88
|
logger.error('Cant get setting from network');
|
|
89
89
|
if (rejectOnFail) {
|
|
90
|
-
throw new
|
|
90
|
+
throw new CannotGetNetworkValueError();
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
this.networkEvents.emit(cacheKey, networkValue);
|
|
@@ -105,56 +105,49 @@ class SettingsManager {
|
|
|
105
105
|
}
|
|
106
106
|
getMultiple(settingsToGet, labels, { timeout = 5000, rejectOnFail = false } = {}) {
|
|
107
107
|
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
throw new Error(`Missing default value for key ${obj.key}`);
|
|
111
|
-
}
|
|
112
|
-
});
|
|
108
|
+
const settingsToReturn = new Map();
|
|
109
|
+
const settingsToFetch = [];
|
|
113
110
|
if (process.env.NODE_ENV === 'test') {
|
|
114
111
|
return settingsToGet.map((obj) => obj.defaultValue);
|
|
115
112
|
}
|
|
116
|
-
settingsToGet.map((obj) =>
|
|
113
|
+
settingsToGet.map((obj) => {
|
|
117
114
|
const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
|
|
118
115
|
const cacheValue = this.settingsCache.get(cacheKey);
|
|
119
|
-
if (cacheValue
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
resolve(SettingsManager.readNetworkValue(networkValue, obj.defaultValue));
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
}
|
|
116
|
+
if (cacheValue) {
|
|
117
|
+
settingsToReturn.set(obj.key, cacheValue);
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
settingsToFetch.push(obj.key);
|
|
128
121
|
}
|
|
129
|
-
}));
|
|
130
|
-
settingsToGet.map((obj) => {
|
|
131
|
-
const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
|
|
132
|
-
this.settingsCache.set(cacheKey, waitingToNetwork, this.ttl);
|
|
133
122
|
});
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
123
|
+
if (settingsToFetch.length > 0) {
|
|
124
|
+
let values;
|
|
125
|
+
try {
|
|
126
|
+
const { data } = yield this.network.get('/api/v1/settings', {
|
|
127
|
+
params: {
|
|
128
|
+
keys: settingsToFetch,
|
|
129
|
+
labels,
|
|
130
|
+
skipEntityQueryAddition: true,
|
|
131
|
+
},
|
|
132
|
+
timeout,
|
|
133
|
+
});
|
|
134
|
+
values = data;
|
|
135
|
+
settingsToFetch.map((key, index) => {
|
|
136
|
+
settingsToReturn.set(key, values[index]);
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
catch (err) {
|
|
140
|
+
logger.error('Cant get setting from network', { err });
|
|
141
|
+
if (rejectOnFail) {
|
|
142
|
+
throw new CannotGetNetworkValueError();
|
|
143
|
+
}
|
|
149
144
|
}
|
|
150
145
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const cacheKey = `${settingsToGet[index].key}_${JSON.stringify(labels)}`;
|
|
154
|
-
this.networkEvents.emit(cacheKey, setting);
|
|
146
|
+
return settingsToGet.map((setting) => {
|
|
147
|
+
const cacheKey = `${setting.key}_${JSON.stringify(labels)}`;
|
|
155
148
|
let returnValue;
|
|
156
149
|
try {
|
|
157
|
-
returnValue = SettingsManager.readNetworkValue(setting,
|
|
150
|
+
returnValue = SettingsManager.readNetworkValue(settingsToReturn.get(setting.key), setting.defaultValue);
|
|
158
151
|
}
|
|
159
152
|
catch (err) {
|
|
160
153
|
this.settingsCache.del(cacheKey);
|
|
@@ -163,7 +156,6 @@ class SettingsManager {
|
|
|
163
156
|
this.settingsCache.set(cacheKey, returnValue, this.ttl);
|
|
164
157
|
return returnValue;
|
|
165
158
|
});
|
|
166
|
-
return settings;
|
|
167
159
|
});
|
|
168
160
|
}
|
|
169
161
|
setLocal(key, labels, value) {
|
package/dist/index.test.js
CHANGED
|
@@ -23,129 +23,188 @@ const mockSetting = (key, value, labels = undefined, response = 200) => {
|
|
|
23
23
|
.query(labels ? { labels } : undefined);
|
|
24
24
|
return n.reply(response, { value });
|
|
25
25
|
};
|
|
26
|
+
const mockMultipleSettings = (keys, values, response = 200) => {
|
|
27
|
+
const n = nock(`http://${serviceUrl}`)
|
|
28
|
+
.get('/api/v1/settings')
|
|
29
|
+
.query({
|
|
30
|
+
keys,
|
|
31
|
+
skipEntityQueryAddition: true,
|
|
32
|
+
});
|
|
33
|
+
return n.reply(response, values);
|
|
34
|
+
};
|
|
26
35
|
describe('Settings', () => {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
const settings = new index_1.default({
|
|
58
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
59
|
-
});
|
|
60
|
-
const value = yield settings.get('key1', 'dv');
|
|
61
|
-
expect(value).toEqual('value1');
|
|
62
|
-
expect(m.isDone()).toBeTruthy();
|
|
63
|
-
}));
|
|
64
|
-
it('Cache from server', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
65
|
-
const m = mockSetting('key1', 'value1');
|
|
66
|
-
const settings = new index_1.default({
|
|
67
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
68
|
-
});
|
|
69
|
-
const value = yield settings.get('key1', 'dv');
|
|
70
|
-
expect(value).toEqual('value1');
|
|
71
|
-
expect(m.isDone()).toBeTruthy();
|
|
72
|
-
const value2 = yield settings.get('key1', 'dv');
|
|
73
|
-
expect(value2).toEqual('value1');
|
|
74
|
-
}));
|
|
75
|
-
it('Use only one request for similar keys', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
76
|
-
const m = mockSetting('key1EM', 'value1EM');
|
|
77
|
-
const settings = new index_1.default({
|
|
78
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
79
|
-
});
|
|
80
|
-
const [value, value2] = yield Promise.all([
|
|
81
|
-
settings.get('key1EM', 'dv'),
|
|
82
|
-
settings.get('key1EM', 'dv'),
|
|
83
|
-
]);
|
|
84
|
-
expect(value).toEqual('value1EM');
|
|
85
|
-
expect(m.isDone()).toBeTruthy();
|
|
86
|
-
expect(value2).toEqual('value1EM');
|
|
87
|
-
}));
|
|
88
|
-
it('Finds with labels', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
-
const labels = [{ fleetId: 'uuid' }];
|
|
90
|
-
const m = mockSetting('key1', 'value1', labels);
|
|
91
|
-
const settings = new index_1.default({
|
|
92
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
93
|
-
});
|
|
94
|
-
const value = yield settings.get('key1', 'dv', labels);
|
|
95
|
-
expect(value).toEqual('value1');
|
|
96
|
-
expect(m.isDone()).toBeTruthy();
|
|
97
|
-
}));
|
|
98
|
-
it('Returns default value when network error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
|
-
const settings = new index_1.default({
|
|
100
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
101
|
-
});
|
|
102
|
-
const value = yield settings.get('key1', 'dv', [{ fleetId: 'uuid' }]);
|
|
103
|
-
expect(value).toEqual('dv');
|
|
104
|
-
}));
|
|
105
|
-
it('Throws an error if network error and no default value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
-
const settings = new index_1.default({
|
|
107
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
108
|
-
});
|
|
109
|
-
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE, [{ fleetId: 'uuid' }]);
|
|
110
|
-
expect(f())
|
|
111
|
-
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
112
|
-
}));
|
|
113
|
-
it('Throws an error if network error and no default value and success the next time', (done) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
-
const settings = new index_1.default({
|
|
115
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
116
|
-
});
|
|
117
|
-
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE);
|
|
118
|
-
expect(f())
|
|
119
|
-
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
120
|
-
setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
36
|
+
describe('get', () => {
|
|
37
|
+
it('Throws exeption if there is no defualt value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
|
+
const settings = new index_1.default({
|
|
39
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
40
|
+
});
|
|
41
|
+
expect(settings.get('key1'))
|
|
42
|
+
.rejects.toEqual(new Error('Can\'t get a key without defaultValue'));
|
|
43
|
+
}));
|
|
44
|
+
it('Can get 0 as default value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
|
+
const settings = new index_1.default({
|
|
46
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
47
|
+
});
|
|
48
|
+
expect(yield settings.get('key1', 0)).toBe(0);
|
|
49
|
+
}));
|
|
50
|
+
it('Can get false as default value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
const settings = new index_1.default({
|
|
52
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
53
|
+
});
|
|
54
|
+
expect(yield settings.get('key1', false)).toBe(false);
|
|
55
|
+
}));
|
|
56
|
+
it('Uses env.SETTING_MS_SERVICE_HOST as service host if no one defined', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
57
|
+
const m = mockSetting('key1', 'value1');
|
|
58
|
+
process.env.SETTING_MS_SERVICE_HOST = serviceUrl;
|
|
59
|
+
const settings = new index_1.default();
|
|
60
|
+
const value = yield settings.get('key1', 'dv');
|
|
61
|
+
expect(value).toEqual('value1');
|
|
62
|
+
expect(m.isDone()).toBeTruthy();
|
|
63
|
+
process.env.SETTING_MS_SERVICE_HOST = '';
|
|
64
|
+
}));
|
|
65
|
+
it('Get a key from server', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
121
66
|
const m = mockSetting('key1', 'value1');
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
67
|
+
const settings = new index_1.default({
|
|
68
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
69
|
+
});
|
|
70
|
+
const value = yield settings.get('key1', 'dv');
|
|
71
|
+
expect(value).toEqual('value1');
|
|
72
|
+
expect(m.isDone()).toBeTruthy();
|
|
73
|
+
}));
|
|
74
|
+
it('Cache from server', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
75
|
+
const m = mockSetting('key1', 'value1');
|
|
76
|
+
const settings = new index_1.default({
|
|
77
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
78
|
+
});
|
|
79
|
+
const value = yield settings.get('key1', 'dv');
|
|
80
|
+
expect(value).toEqual('value1');
|
|
81
|
+
expect(m.isDone()).toBeTruthy();
|
|
82
|
+
const value2 = yield settings.get('key1', 'dv');
|
|
83
|
+
expect(value2).toEqual('value1');
|
|
84
|
+
}));
|
|
85
|
+
it('Use only one request for similar keys', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
86
|
+
const m = mockSetting('key1EM', 'value1EM');
|
|
87
|
+
const settings = new index_1.default({
|
|
88
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
89
|
+
});
|
|
90
|
+
const [value, value2] = yield Promise.all([
|
|
91
|
+
settings.get('key1EM', 'dv'),
|
|
92
|
+
settings.get('key1EM', 'dv'),
|
|
93
|
+
]);
|
|
94
|
+
expect(value).toEqual('value1EM');
|
|
95
|
+
expect(m.isDone()).toBeTruthy();
|
|
96
|
+
expect(value2).toEqual('value1EM');
|
|
97
|
+
}));
|
|
98
|
+
it('Finds with labels', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
99
|
+
const labels = [{ fleetId: 'uuid' }];
|
|
100
|
+
const m = mockSetting('key1', 'value1', labels);
|
|
101
|
+
const settings = new index_1.default({
|
|
102
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
103
|
+
});
|
|
104
|
+
const value = yield settings.get('key1', 'dv', labels);
|
|
105
|
+
expect(value).toEqual('value1');
|
|
106
|
+
expect(m.isDone()).toBeTruthy();
|
|
107
|
+
}));
|
|
108
|
+
it('Returns default value when network error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
109
|
+
const settings = new index_1.default({
|
|
110
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
111
|
+
});
|
|
112
|
+
const value = yield settings.get('key1', 'dv', [{ fleetId: 'uuid' }]);
|
|
113
|
+
expect(value).toEqual('dv');
|
|
114
|
+
}));
|
|
115
|
+
it('Throws an error if network error and no default value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
116
|
+
const settings = new index_1.default({
|
|
117
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
118
|
+
});
|
|
119
|
+
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE, [{ fleetId: 'uuid' }]);
|
|
120
|
+
expect(f())
|
|
121
|
+
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
122
|
+
}));
|
|
123
|
+
it('Throws an error if network error and no default value and success the next time', (done) => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
|
+
const settings = new index_1.default({
|
|
125
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
126
|
+
});
|
|
127
|
+
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE);
|
|
128
|
+
expect(f())
|
|
129
|
+
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
130
|
+
setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
131
|
+
const m = mockSetting('key1', 'value1');
|
|
132
|
+
expect(yield settings.get('key1', settings.NEVER_DEFAULT_VALUE)).toEqual('value1');
|
|
133
|
+
expect(m.isDone());
|
|
134
|
+
done();
|
|
135
|
+
}), 100);
|
|
136
|
+
}));
|
|
137
|
+
it('Values can be flushed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
138
|
+
const m1 = mockSetting('key1', 'value1');
|
|
139
|
+
const settings = new index_1.default({
|
|
140
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
141
|
+
});
|
|
142
|
+
settings.flush();
|
|
143
|
+
const value = yield settings.get('key1', 'dv');
|
|
144
|
+
expect(value).toEqual('value1');
|
|
145
|
+
expect(m1.isDone()).toBeTruthy();
|
|
146
|
+
settings.flush();
|
|
147
|
+
const m2 = mockSetting('key1', 'value2');
|
|
148
|
+
const value2 = yield settings.get('key1', 'dv');
|
|
149
|
+
expect(value2).toEqual('value2');
|
|
150
|
+
expect(m2.isDone()).toBeTruthy();
|
|
151
|
+
}));
|
|
152
|
+
it('when NODE_ENV === test return the default value', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
153
|
+
process.env.NODE_ENV = 'test';
|
|
154
|
+
const settings = new index_1.default({
|
|
155
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
156
|
+
});
|
|
157
|
+
const value = yield settings.get('key1', 'dv');
|
|
158
|
+
expect(value).toEqual('dv');
|
|
159
|
+
process.env.NODE_ENV = 'node-common-test';
|
|
160
|
+
}));
|
|
161
|
+
});
|
|
162
|
+
describe('getMultiple', () => {
|
|
163
|
+
it('when NODE_ENV === test return the default values', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
164
|
+
process.env.NODE_ENV = 'test';
|
|
165
|
+
const settings = new index_1.default({
|
|
166
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
167
|
+
});
|
|
168
|
+
const values = yield settings.getMultiple([
|
|
169
|
+
{
|
|
170
|
+
key: 'key0',
|
|
171
|
+
defaultValue: 'defaultValue0',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
key: 'key1',
|
|
175
|
+
defaultValue: 'defaultValue1',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
key: 'key2',
|
|
179
|
+
defaultValue: 'defaultValue2',
|
|
180
|
+
},
|
|
181
|
+
], []);
|
|
182
|
+
values.map((value, i) => expect(value).toEqual(`defaultValue${i}`));
|
|
183
|
+
process.env.NODE_ENV = 'node-common-test';
|
|
184
|
+
}));
|
|
185
|
+
it('can get multiple settings', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
+
const mock = mockMultipleSettings(['key0', 'key1', 'key2'], ['value0', 'value1', 'value2']);
|
|
187
|
+
const settings = new index_1.default({
|
|
188
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
189
|
+
});
|
|
190
|
+
const values = yield settings.getMultiple([
|
|
191
|
+
{
|
|
192
|
+
key: 'key0',
|
|
193
|
+
defaultValue: 'defaultValue0',
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
key: 'key1',
|
|
197
|
+
defaultValue: 'defaultValue1',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
key: 'key2',
|
|
201
|
+
defaultValue: 'defaultValue2',
|
|
202
|
+
},
|
|
203
|
+
], []);
|
|
204
|
+
expect(mock.isDone()).toBeTruthy();
|
|
205
|
+
values.forEach((v, index) => {
|
|
206
|
+
expect(v).toEqual(`value${index}`);
|
|
207
|
+
});
|
|
208
|
+
}));
|
|
209
|
+
});
|
|
151
210
|
});
|
package/package.json
CHANGED
package/src/index.test.ts
CHANGED
|
@@ -15,158 +15,226 @@ const mockSetting = (key: string, value: string | boolean | number | never, labe
|
|
|
15
15
|
return n.reply(response, { value });
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
const mockMultipleSettings = (keys: string[], values: string[], response = 200) => {
|
|
19
|
+
const n = nock(`http://${serviceUrl}`)
|
|
20
|
+
.get('/api/v1/settings')
|
|
21
|
+
.query({
|
|
22
|
+
keys,
|
|
23
|
+
skipEntityQueryAddition: true,
|
|
22
24
|
});
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
});
|
|
26
|
+
return n.reply(response, values);
|
|
27
|
+
};
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
describe('Settings', () => {
|
|
30
|
+
describe('get', () => {
|
|
31
|
+
it('Throws exeption if there is no defualt value', async () => {
|
|
32
|
+
const settings = new Settings({
|
|
33
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
expect(settings.get('key1'))
|
|
37
|
+
.rejects.toEqual(new Error('Can\'t get a key without defaultValue'));
|
|
31
38
|
});
|
|
32
39
|
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
it('Can get 0 as default value', async () => {
|
|
41
|
+
const settings = new Settings({
|
|
42
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
43
|
+
});
|
|
35
44
|
|
|
36
|
-
|
|
37
|
-
const settings = new Settings({
|
|
38
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
45
|
+
expect(await settings.get('key1', 0)).toBe(0);
|
|
39
46
|
});
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
48
|
+
it('Can get false as default value', async () => {
|
|
49
|
+
const settings = new Settings({
|
|
50
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
51
|
+
});
|
|
43
52
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
process.env.SETTING_MS_SERVICE_HOST = serviceUrl;
|
|
47
|
-
const settings = new Settings();
|
|
53
|
+
expect(await settings.get('key1', false)).toBe(false);
|
|
54
|
+
});
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
56
|
+
it('Uses env.SETTING_MS_SERVICE_HOST as service host if no one defined', async () => {
|
|
57
|
+
const m = mockSetting('key1', 'value1');
|
|
58
|
+
process.env.SETTING_MS_SERVICE_HOST = serviceUrl;
|
|
59
|
+
const settings = new Settings();
|
|
54
60
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
const value = await settings.get('key1', 'dv');
|
|
62
|
+
expect(value).toEqual('value1');
|
|
63
|
+
expect(m.isDone()).toBeTruthy();
|
|
64
|
+
process.env.SETTING_MS_SERVICE_HOST = '';
|
|
59
65
|
});
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
it('Get a key from server', async () => {
|
|
68
|
+
const m = mockSetting('key1', 'value1');
|
|
69
|
+
const settings = new Settings({
|
|
70
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
71
|
+
});
|
|
65
72
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
73
|
+
const value = await settings.get('key1', 'dv');
|
|
74
|
+
expect(value).toEqual('value1');
|
|
75
|
+
expect(m.isDone()).toBeTruthy();
|
|
70
76
|
});
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
it('Cache from server', async () => {
|
|
79
|
+
const m = mockSetting('key1', 'value1');
|
|
80
|
+
const settings = new Settings({
|
|
81
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
82
|
+
});
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
const value = await settings.get('key1', 'dv');
|
|
85
|
+
expect(value).toEqual('value1');
|
|
86
|
+
expect(m.isDone()).toBeTruthy();
|
|
79
87
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const settings = new Settings({
|
|
83
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
88
|
+
const value2 = await settings.get('key1', 'dv');
|
|
89
|
+
expect(value2).toEqual('value1');
|
|
84
90
|
});
|
|
85
91
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
settings
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
expect(m.isDone()).toBeTruthy();
|
|
92
|
+
it('Use only one request for similar keys', async () => {
|
|
93
|
+
const m = mockSetting('key1EM', 'value1EM');
|
|
94
|
+
const settings = new Settings({
|
|
95
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
96
|
+
});
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
const [value, value2] = await Promise.all([
|
|
99
|
+
settings.get('key1EM', 'dv'),
|
|
100
|
+
settings.get('key1EM', 'dv'),
|
|
101
|
+
]);
|
|
102
|
+
expect(value).toEqual('value1EM');
|
|
103
|
+
expect(m.isDone()).toBeTruthy();
|
|
95
104
|
|
|
96
|
-
|
|
97
|
-
const labels = [{ fleetId: 'uuid' }];
|
|
98
|
-
const m = mockSetting('key1', 'value1', labels);
|
|
99
|
-
const settings = new Settings({
|
|
100
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
105
|
+
expect(value2).toEqual('value1EM');
|
|
101
106
|
});
|
|
102
107
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
it('Finds with labels', async () => {
|
|
109
|
+
const labels = [{ fleetId: 'uuid' }];
|
|
110
|
+
const m = mockSetting('key1', 'value1', labels);
|
|
111
|
+
const settings = new Settings({
|
|
112
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
113
|
+
});
|
|
107
114
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
115
|
+
const value = await settings.get('key1', 'dv', labels);
|
|
116
|
+
expect(value).toEqual('value1');
|
|
117
|
+
expect(m.isDone()).toBeTruthy();
|
|
111
118
|
});
|
|
112
119
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
120
|
+
it('Returns default value when network error', async () => {
|
|
121
|
+
const settings = new Settings({
|
|
122
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
123
|
+
});
|
|
116
124
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
serviceUrl: `http://${serviceUrl}/`,
|
|
125
|
+
const value = await settings.get('key1', 'dv', [{ fleetId: 'uuid' }]);
|
|
126
|
+
expect(value).toEqual('dv');
|
|
120
127
|
});
|
|
121
128
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
it('Throws an error if network error and no default value', async () => {
|
|
130
|
+
const settings = new Settings({
|
|
131
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
132
|
+
});
|
|
126
133
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
134
|
+
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE, [{ fleetId: 'uuid' }]);
|
|
135
|
+
expect(f())
|
|
136
|
+
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
130
137
|
});
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
it('Throws an error if network error and no default value and success the next time', async (done) => {
|
|
140
|
+
const settings = new Settings({
|
|
141
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE);
|
|
145
|
+
expect(f())
|
|
146
|
+
.rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
|
|
147
|
+
|
|
148
|
+
setTimeout(async () => {
|
|
149
|
+
const m = mockSetting('key1', 'value1');
|
|
150
|
+
expect(await settings.get('key1', settings.NEVER_DEFAULT_VALUE)).toEqual('value1');
|
|
151
|
+
expect(m.isDone());
|
|
152
|
+
done();
|
|
153
|
+
}, 100);
|
|
154
|
+
});
|
|
135
155
|
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
});
|
|
156
|
+
it('Values can be flushed', async () => {
|
|
157
|
+
const m1 = mockSetting('key1', 'value1');
|
|
158
|
+
const settings = new Settings({
|
|
159
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
160
|
+
});
|
|
161
|
+
settings.flush();
|
|
143
162
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
163
|
+
const value = await settings.get('key1', 'dv');
|
|
164
|
+
expect(value).toEqual('value1');
|
|
165
|
+
expect(m1.isDone()).toBeTruthy();
|
|
166
|
+
|
|
167
|
+
settings.flush();
|
|
168
|
+
const m2 = mockSetting('key1', 'value2');
|
|
150
169
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
const value2 = await settings.get('key1', 'dv');
|
|
171
|
+
expect(value2).toEqual('value2');
|
|
172
|
+
expect(m2.isDone()).toBeTruthy();
|
|
173
|
+
});
|
|
154
174
|
|
|
155
|
-
|
|
156
|
-
|
|
175
|
+
it('when NODE_ENV === test return the default value', async () => {
|
|
176
|
+
process.env.NODE_ENV = 'test';
|
|
177
|
+
const settings = new Settings({
|
|
178
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
179
|
+
});
|
|
157
180
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
181
|
+
const value = await settings.get('key1', 'dv');
|
|
182
|
+
expect(value).toEqual('dv');
|
|
183
|
+
process.env.NODE_ENV = 'node-common-test';
|
|
184
|
+
});
|
|
161
185
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
186
|
+
|
|
187
|
+
describe('getMultiple', () => {
|
|
188
|
+
it('when NODE_ENV === test return the default values', async () => {
|
|
189
|
+
process.env.NODE_ENV = 'test';
|
|
190
|
+
const settings = new Settings({
|
|
191
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
const values = await settings.getMultiple([
|
|
195
|
+
{
|
|
196
|
+
key: 'key0',
|
|
197
|
+
defaultValue: 'defaultValue0',
|
|
198
|
+
},
|
|
199
|
+
{
|
|
200
|
+
key: 'key1',
|
|
201
|
+
defaultValue: 'defaultValue1',
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
key: 'key2',
|
|
205
|
+
defaultValue: 'defaultValue2',
|
|
206
|
+
},
|
|
207
|
+
], []);
|
|
208
|
+
values.map((value: any, i: number) => expect(value).toEqual(`defaultValue${i}`));
|
|
209
|
+
process.env.NODE_ENV = 'node-common-test';
|
|
166
210
|
});
|
|
167
211
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
212
|
+
it('can get multiple settings', async () => {
|
|
213
|
+
const mock = mockMultipleSettings(['key0', 'key1', 'key2'], ['value0', 'value1', 'value2']);
|
|
214
|
+
|
|
215
|
+
const settings = new Settings({
|
|
216
|
+
serviceUrl: `http://${serviceUrl}/`,
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
const values = await settings.getMultiple([
|
|
220
|
+
{
|
|
221
|
+
key: 'key0',
|
|
222
|
+
defaultValue: 'defaultValue0',
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
key: 'key1',
|
|
226
|
+
defaultValue: 'defaultValue1',
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
key: 'key2',
|
|
230
|
+
defaultValue: 'defaultValue2',
|
|
231
|
+
},
|
|
232
|
+
], []);
|
|
233
|
+
|
|
234
|
+
expect(mock.isDone()).toBeTruthy();
|
|
235
|
+
values.forEach((v: any, index: number) => {
|
|
236
|
+
expect(v).toEqual(`value${index}`);
|
|
237
|
+
});
|
|
238
|
+
});
|
|
171
239
|
});
|
|
172
240
|
});
|
package/src/index.ts
CHANGED
|
@@ -40,7 +40,7 @@ interface GetSettingOption {
|
|
|
40
40
|
rejectOnFail?: boolean;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
class
|
|
43
|
+
class CannotGetNetworkValueError extends Error {}
|
|
44
44
|
|
|
45
45
|
class SettingsManager {
|
|
46
46
|
ttl: number;
|
|
@@ -121,7 +121,7 @@ class SettingsManager {
|
|
|
121
121
|
} catch (error) {
|
|
122
122
|
logger.error('Cant get setting from network');
|
|
123
123
|
if (rejectOnFail) {
|
|
124
|
-
throw new
|
|
124
|
+
throw new CannotGetNetworkValueError();
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
@@ -145,60 +145,51 @@ class SettingsManager {
|
|
|
145
145
|
labels: LabelsArray,
|
|
146
146
|
{ timeout = 5000, rejectOnFail = false } : GetSettingOption = {},
|
|
147
147
|
): Promise<any> {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
throw new Error(`Missing default value for key ${obj.key}`);
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
|
|
148
|
+
const settingsToReturn = new Map();
|
|
149
|
+
const settingsToFetch: any[] = [];
|
|
154
150
|
if (process.env.NODE_ENV === 'test') {
|
|
155
151
|
return settingsToGet.map((obj) => obj.defaultValue);
|
|
156
152
|
}
|
|
157
153
|
|
|
158
|
-
settingsToGet.map(
|
|
154
|
+
settingsToGet.map((obj) => {
|
|
159
155
|
const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
|
|
160
156
|
const cacheValue = this.settingsCache.get(cacheKey);
|
|
161
|
-
if (cacheValue
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.networkEvents.once(cacheKey, (networkValue) => {
|
|
166
|
-
resolve(SettingsManager.readNetworkValue(networkValue, obj.defaultValue));
|
|
167
|
-
});
|
|
168
|
-
});
|
|
169
|
-
}
|
|
157
|
+
if (cacheValue) {
|
|
158
|
+
settingsToReturn.set(obj.key, cacheValue);
|
|
159
|
+
} else {
|
|
160
|
+
settingsToFetch.push(obj.key);
|
|
170
161
|
}
|
|
171
162
|
});
|
|
172
163
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
164
|
+
if (settingsToFetch.length > 0) {
|
|
165
|
+
let values: any[];
|
|
166
|
+
try {
|
|
167
|
+
const { data } = await this.network.get('/api/v1/settings', {
|
|
168
|
+
params: {
|
|
169
|
+
keys: settingsToFetch,
|
|
170
|
+
labels,
|
|
171
|
+
skipEntityQueryAddition: true,
|
|
172
|
+
},
|
|
173
|
+
timeout,
|
|
174
|
+
});
|
|
175
|
+
values = data;
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
});
|
|
187
|
-
settings = data;
|
|
188
|
-
} catch (err) {
|
|
189
|
-
logger.error('Cant get setting from network');
|
|
190
|
-
if (rejectOnFail) {
|
|
191
|
-
throw new ConnotGetNetworkValueError();
|
|
177
|
+
settingsToFetch.map((key, index) => {
|
|
178
|
+
settingsToReturn.set(key, values[index]);
|
|
179
|
+
});
|
|
180
|
+
} catch (err) {
|
|
181
|
+
logger.error('Cant get setting from network', { err });
|
|
182
|
+
if (rejectOnFail) {
|
|
183
|
+
throw new CannotGetNetworkValueError();
|
|
184
|
+
}
|
|
192
185
|
}
|
|
193
186
|
}
|
|
194
187
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const cacheKey = `${settingsToGet[index].key}_${JSON.stringify(labels)}`;
|
|
198
|
-
this.networkEvents.emit(cacheKey, setting);
|
|
188
|
+
return settingsToGet.map((setting: any) => {
|
|
189
|
+
const cacheKey = `${setting.key}_${JSON.stringify(labels)}`;
|
|
199
190
|
let returnValue;
|
|
200
191
|
try {
|
|
201
|
-
returnValue = SettingsManager.readNetworkValue(setting,
|
|
192
|
+
returnValue = SettingsManager.readNetworkValue(settingsToReturn.get(setting.key), setting.defaultValue);
|
|
202
193
|
} catch (err) {
|
|
203
194
|
this.settingsCache.del(cacheKey);
|
|
204
195
|
throw err;
|
|
@@ -206,8 +197,6 @@ class SettingsManager {
|
|
|
206
197
|
this.settingsCache.set(cacheKey, returnValue, this.ttl);
|
|
207
198
|
return returnValue;
|
|
208
199
|
});
|
|
209
|
-
|
|
210
|
-
return settings;
|
|
211
200
|
}
|
|
212
201
|
|
|
213
202
|
setLocal(key: string, labels: LabelsArray, value: SettingValue) {
|