@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 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 ConnotGetNetworkValueError extends Error {
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 ConnotGetNetworkValueError();
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
- settingsToGet.map((obj) => {
109
- if (typeof obj.defaultValue === 'undefined') {
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) => __awaiter(this, void 0, void 0, function* () {
113
+ settingsToGet.map((obj) => {
117
114
  const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
118
115
  const cacheValue = this.settingsCache.get(cacheKey);
119
- if (cacheValue !== undefined) {
120
- if (waitingToNetwork === cacheValue) {
121
- yield nextTick();
122
- return new Promise((resolve) => {
123
- this.networkEvents.once(cacheKey, (networkValue) => {
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
- let settings;
135
- try {
136
- const { data } = yield this.network.get('/api/v1/settings', {
137
- params: {
138
- keys: settingsToGet.map((obj) => obj.key),
139
- labels,
140
- },
141
- timeout,
142
- });
143
- settings = data;
144
- }
145
- catch (err) {
146
- logger.error('Cant get setting from network');
147
- if (rejectOnFail) {
148
- throw new ConnotGetNetworkValueError();
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
- // eslint-disable-next-line array-callback-return
152
- settings.map((setting, index) => {
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, settingsToGet[index].defaultValue);
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) {
@@ -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
- it('Throws exeption if there is no defualt value', () => __awaiter(void 0, void 0, void 0, function* () {
28
- const settings = new index_1.default({
29
- serviceUrl: `http://${serviceUrl}/`,
30
- });
31
- expect(settings.get('key1'))
32
- .rejects.toEqual(new Error('Can\'t get a key without defaultValue'));
33
- }));
34
- it('Can get 0 as default value', () => __awaiter(void 0, void 0, void 0, function* () {
35
- const settings = new index_1.default({
36
- serviceUrl: `http://${serviceUrl}/`,
37
- });
38
- expect(yield settings.get('key1', 0)).toBe(0);
39
- }));
40
- it('Can get false as default value', () => __awaiter(void 0, void 0, void 0, function* () {
41
- const settings = new index_1.default({
42
- serviceUrl: `http://${serviceUrl}/`,
43
- });
44
- expect(yield settings.get('key1', false)).toBe(false);
45
- }));
46
- it('Uses env.SETTING_MS_SERVICE_HOST as service host if no one defined', () => __awaiter(void 0, void 0, void 0, function* () {
47
- const m = mockSetting('key1', 'value1');
48
- process.env.SETTING_MS_SERVICE_HOST = serviceUrl;
49
- const settings = new index_1.default();
50
- const value = yield settings.get('key1', 'dv');
51
- expect(value).toEqual('value1');
52
- expect(m.isDone()).toBeTruthy();
53
- process.env.SETTING_MS_SERVICE_HOST = '';
54
- }));
55
- it('Get a key from server', () => __awaiter(void 0, void 0, void 0, function* () {
56
- const m = mockSetting('key1', 'value1');
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
- expect(yield settings.get('key1', settings.NEVER_DEFAULT_VALUE)).toEqual('value1');
123
- expect(m.isDone());
124
- done();
125
- }), 100);
126
- }));
127
- it('Values can be flushed', () => __awaiter(void 0, void 0, void 0, function* () {
128
- const m1 = mockSetting('key1', 'value1');
129
- const settings = new index_1.default({
130
- serviceUrl: `http://${serviceUrl}/`,
131
- });
132
- settings.flush();
133
- const value = yield settings.get('key1', 'dv');
134
- expect(value).toEqual('value1');
135
- expect(m1.isDone()).toBeTruthy();
136
- settings.flush();
137
- const m2 = mockSetting('key1', 'value2');
138
- const value2 = yield settings.get('key1', 'dv');
139
- expect(value2).toEqual('value2');
140
- expect(m2.isDone()).toBeTruthy();
141
- }));
142
- it('when NODE_ENV === test return the default value', () => __awaiter(void 0, void 0, void 0, function* () {
143
- process.env.NODE_ENV = 'test';
144
- const settings = new index_1.default({
145
- serviceUrl: `http://${serviceUrl}/`,
146
- });
147
- const value = yield settings.get('key1', 'dv');
148
- expect(value).toEqual('dv');
149
- process.env.NODE_ENV = 'node-common-test';
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@autofleet/settings",
3
- "version": "1.0.5-beta-3",
3
+ "version": "1.0.6",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
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
- describe('Settings', () => {
19
- it('Throws exeption if there is no defualt value', async () => {
20
- const settings = new Settings({
21
- serviceUrl: `http://${serviceUrl}/`,
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
- expect(settings.get('key1'))
25
- .rejects.toEqual(new Error('Can\'t get a key without defaultValue'));
26
- });
26
+ return n.reply(response, values);
27
+ };
27
28
 
28
- it('Can get 0 as default value', async () => {
29
- const settings = new Settings({
30
- serviceUrl: `http://${serviceUrl}/`,
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
- expect(await settings.get('key1', 0)).toBe(0);
34
- });
40
+ it('Can get 0 as default value', async () => {
41
+ const settings = new Settings({
42
+ serviceUrl: `http://${serviceUrl}/`,
43
+ });
35
44
 
36
- it('Can get false as default value', async () => {
37
- const settings = new Settings({
38
- serviceUrl: `http://${serviceUrl}/`,
45
+ expect(await settings.get('key1', 0)).toBe(0);
39
46
  });
40
47
 
41
- expect(await settings.get('key1', false)).toBe(false);
42
- });
48
+ it('Can get false as default value', async () => {
49
+ const settings = new Settings({
50
+ serviceUrl: `http://${serviceUrl}/`,
51
+ });
43
52
 
44
- it('Uses env.SETTING_MS_SERVICE_HOST as service host if no one defined', async () => {
45
- const m = mockSetting('key1', 'value1');
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
- const value = await settings.get('key1', 'dv');
50
- expect(value).toEqual('value1');
51
- expect(m.isDone()).toBeTruthy();
52
- process.env.SETTING_MS_SERVICE_HOST = '';
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
- it('Get a key from server', async () => {
56
- const m = mockSetting('key1', 'value1');
57
- const settings = new Settings({
58
- serviceUrl: `http://${serviceUrl}/`,
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
- const value = await settings.get('key1', 'dv');
62
- expect(value).toEqual('value1');
63
- expect(m.isDone()).toBeTruthy();
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
- it('Cache from server', async () => {
67
- const m = mockSetting('key1', 'value1');
68
- const settings = new Settings({
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
- const value = await settings.get('key1', 'dv');
73
- expect(value).toEqual('value1');
74
- expect(m.isDone()).toBeTruthy();
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
- const value2 = await settings.get('key1', 'dv');
77
- expect(value2).toEqual('value1');
78
- });
84
+ const value = await settings.get('key1', 'dv');
85
+ expect(value).toEqual('value1');
86
+ expect(m.isDone()).toBeTruthy();
79
87
 
80
- it('Use only one request for similar keys', async () => {
81
- const m = mockSetting('key1EM', 'value1EM');
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
- const [value, value2] = await Promise.all([
87
- settings.get('key1EM', 'dv'),
88
- settings.get('key1EM', 'dv'),
89
- ]);
90
- expect(value).toEqual('value1EM');
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
- expect(value2).toEqual('value1EM');
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
- it('Finds with labels', async () => {
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
- const value = await settings.get('key1', 'dv', labels);
104
- expect(value).toEqual('value1');
105
- expect(m.isDone()).toBeTruthy();
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
- it('Returns default value when network error', async () => {
109
- const settings = new Settings({
110
- serviceUrl: `http://${serviceUrl}/`,
115
+ const value = await settings.get('key1', 'dv', labels);
116
+ expect(value).toEqual('value1');
117
+ expect(m.isDone()).toBeTruthy();
111
118
  });
112
119
 
113
- const value = await settings.get('key1', 'dv', [{ fleetId: 'uuid' }]);
114
- expect(value).toEqual('dv');
115
- });
120
+ it('Returns default value when network error', async () => {
121
+ const settings = new Settings({
122
+ serviceUrl: `http://${serviceUrl}/`,
123
+ });
116
124
 
117
- it('Throws an error if network error and no default value', async () => {
118
- const settings = new Settings({
119
- serviceUrl: `http://${serviceUrl}/`,
125
+ const value = await settings.get('key1', 'dv', [{ fleetId: 'uuid' }]);
126
+ expect(value).toEqual('dv');
120
127
  });
121
128
 
122
- const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE, [{ fleetId: 'uuid' }]);
123
- expect(f())
124
- .rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
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
- it('Throws an error if network error and no default value and success the next time', async (done) => {
128
- const settings = new Settings({
129
- serviceUrl: `http://${serviceUrl}/`,
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
- const f = () => settings.get('key1', settings.NEVER_DEFAULT_VALUE);
133
- expect(f())
134
- .rejects.toEqual(new Error('Cannot find value from network or cache, default value is set to never'));
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
- setTimeout(async () => {
137
- const m = mockSetting('key1', 'value1');
138
- expect(await settings.get('key1', settings.NEVER_DEFAULT_VALUE)).toEqual('value1');
139
- expect(m.isDone());
140
- done();
141
- }, 100);
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
- it('Values can be flushed', async () => {
145
- const m1 = mockSetting('key1', 'value1');
146
- const settings = new Settings({
147
- serviceUrl: `http://${serviceUrl}/`,
148
- });
149
- settings.flush();
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
- const value = await settings.get('key1', 'dv');
152
- expect(value).toEqual('value1');
153
- expect(m1.isDone()).toBeTruthy();
170
+ const value2 = await settings.get('key1', 'dv');
171
+ expect(value2).toEqual('value2');
172
+ expect(m2.isDone()).toBeTruthy();
173
+ });
154
174
 
155
- settings.flush();
156
- const m2 = mockSetting('key1', 'value2');
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
- const value2 = await settings.get('key1', 'dv');
159
- expect(value2).toEqual('value2');
160
- expect(m2.isDone()).toBeTruthy();
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
- it('when NODE_ENV === test return the default value', async () => {
163
- process.env.NODE_ENV = 'test';
164
- const settings = new Settings({
165
- serviceUrl: `http://${serviceUrl}/`,
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
- const value = await settings.get('key1', 'dv');
169
- expect(value).toEqual('dv');
170
- process.env.NODE_ENV = 'node-common-test';
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 ConnotGetNetworkValueError extends Error {}
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 ConnotGetNetworkValueError();
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
- settingsToGet.map((obj) => {
149
- if (typeof obj.defaultValue === 'undefined') {
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(async (obj) => {
154
+ settingsToGet.map((obj) => {
159
155
  const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
160
156
  const cacheValue = this.settingsCache.get(cacheKey);
161
- if (cacheValue !== undefined) {
162
- if (waitingToNetwork === cacheValue) {
163
- await nextTick();
164
- return new Promise((resolve) => {
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
- settingsToGet.map((obj) => {
174
- const cacheKey = `${obj.key}_${JSON.stringify(labels)}`;
175
- this.settingsCache.set(cacheKey, waitingToNetwork, this.ttl);
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
- let settings;
179
- try {
180
- const { data } = await this.network.get('/api/v1/settings', {
181
- params: {
182
- keys: settingsToGet.map((obj) => obj.key),
183
- labels,
184
- },
185
- timeout,
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
- // eslint-disable-next-line array-callback-return
196
- settings.map((setting: any, index: number) => {
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, settingsToGet[index].defaultValue);
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) {