@iobroker/db-objects-file 4.0.21 → 4.1.0-alpha.0-20220819-74ceeddc
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/build/index.d.ts +5 -0
- package/{index.js → build/index.js} +2 -0
- package/build/lib/objects/objectsInMemFileDB.d.ts +100 -0
- package/build/lib/objects/objectsInMemFileDB.d.ts.map +1 -0
- package/{lib → build/lib}/objects/objectsInMemFileDB.js +125 -210
- package/build/lib/objects/objectsInMemFileDB.js.map +1 -0
- package/build/lib/objects/objectsInMemServerClass.d.ts +14 -0
- package/build/lib/objects/objectsInMemServerClass.d.ts.map +1 -0
- package/{lib → build/lib}/objects/objectsInMemServerClass.js +1 -9
- package/build/lib/objects/objectsInMemServerClass.js.map +1 -0
- package/build/lib/objects/objectsInMemServerRedis.d.ts +89 -0
- package/build/lib/objects/objectsInMemServerRedis.d.ts.map +1 -0
- package/{lib → build/lib}/objects/objectsInMemServerRedis.js +218 -285
- package/build/lib/objects/objectsInMemServerRedis.js.map +1 -0
- package/package.json +13 -9
|
@@ -6,9 +6,7 @@
|
|
|
6
6
|
* MIT License
|
|
7
7
|
*
|
|
8
8
|
*/
|
|
9
|
-
|
|
10
9
|
/** @module objectsInRedis */
|
|
11
|
-
|
|
12
10
|
/* jshint -W097 */
|
|
13
11
|
/* jshint strict:false */
|
|
14
12
|
/* jslint node: true */
|
|
@@ -19,10 +17,8 @@ const path = require('path');
|
|
|
19
17
|
const crypto = require('crypto');
|
|
20
18
|
const utils = require('@iobroker/db-objects-redis').objectsUtils;
|
|
21
19
|
const tools = require('@iobroker/db-base').tools;
|
|
22
|
-
|
|
23
|
-
const RedisHandler = require('@iobroker/db-base').redisHandler;
|
|
20
|
+
const { RedisHandler } = require('@iobroker/db-base');
|
|
24
21
|
const ObjectsInMemoryFileDB = require('./objectsInMemFileDB');
|
|
25
|
-
|
|
26
22
|
// settings = {
|
|
27
23
|
// change: function (id, state) {},
|
|
28
24
|
// connected: function (nameOfServer) {},
|
|
@@ -43,7 +39,6 @@ const ObjectsInMemoryFileDB = require('./objectsInMemFileDB');
|
|
|
43
39
|
// host: localhost
|
|
44
40
|
// };
|
|
45
41
|
//
|
|
46
|
-
|
|
47
42
|
/**
|
|
48
43
|
* This class inherits statesInMemoryFileDB class and adds redis communication layer
|
|
49
44
|
* to access the methods via redis protocol
|
|
@@ -55,11 +50,10 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
55
50
|
*/
|
|
56
51
|
constructor(settings) {
|
|
57
52
|
super(settings);
|
|
58
|
-
|
|
59
53
|
this.serverConnections = {};
|
|
60
54
|
this.namespaceObjects =
|
|
61
55
|
(this.settings.redisNamespace || (settings.connection && settings.connection.redisNamespace) || 'cfg') +
|
|
62
|
-
|
|
56
|
+
'.';
|
|
63
57
|
this.namespaceFile = this.namespaceObjects + 'f.';
|
|
64
58
|
this.namespaceObj = this.namespaceObjects + 'o.';
|
|
65
59
|
this.namespaceSet = this.namespaceObjects + 's.';
|
|
@@ -67,39 +61,30 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
67
61
|
// this.namespaceObjectsLen = this.namespaceObjects.length;
|
|
68
62
|
this.namespaceFileLen = this.namespaceFile.length;
|
|
69
63
|
this.namespaceObjLen = this.namespaceObj.length;
|
|
70
|
-
this.
|
|
71
|
-
this.
|
|
72
|
-
|
|
64
|
+
this.namespaceMeta = `${this.settings.namespaceMeta || 'meta'}.`;
|
|
65
|
+
this.namespaceMetaLen = this.namespaceMeta.length;
|
|
73
66
|
this.knownScripts = {};
|
|
74
|
-
|
|
75
67
|
this.normalizeFileRegex1 = new RegExp('^(.*)\\$%\\$(.*)\\$%\\$(meta|data)$');
|
|
76
68
|
this.normalizeFileRegex2 = new RegExp('^(.*)\\$%\\$(.*)\\/?\\*$');
|
|
77
|
-
|
|
78
69
|
this.open()
|
|
79
70
|
.then(() => {
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
return this._initRedisServer(this.settings.connection);
|
|
72
|
+
})
|
|
82
73
|
.then(() => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
setImmediate(() => this.settings.connected());
|
|
93
|
-
}
|
|
94
|
-
})
|
|
74
|
+
this.log.debug(this.namespace +
|
|
75
|
+
' ' +
|
|
76
|
+
(settings.secure ? 'Secure ' : '') +
|
|
77
|
+
' Redis inMem-objects listening on port ' +
|
|
78
|
+
(settings.port || 9001));
|
|
79
|
+
if (typeof this.settings.connected === 'function') {
|
|
80
|
+
setImmediate(() => this.settings.connected());
|
|
81
|
+
}
|
|
82
|
+
})
|
|
95
83
|
.catch(e => {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
process.exit(24); // todo: replace it with exitcode
|
|
100
|
-
});
|
|
84
|
+
this.log.error(`${this.namespace} Cannot start inMem-objects on port ${settings.port || 9001}: ${e.message}`);
|
|
85
|
+
process.exit(24); // todo: replace it with exitcode
|
|
86
|
+
});
|
|
101
87
|
}
|
|
102
|
-
|
|
103
88
|
/**
|
|
104
89
|
* Separate Namespace from ID and return both
|
|
105
90
|
* @param idWithNamespace ID or Array of IDs containing a redis namespace and the real ID
|
|
@@ -120,18 +105,20 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
120
105
|
ns = namespace; // we ignore the pot. case from arrays with different namespaces
|
|
121
106
|
});
|
|
122
107
|
id = ids;
|
|
123
|
-
}
|
|
108
|
+
}
|
|
109
|
+
else if (typeof idWithNamespace === 'string') {
|
|
124
110
|
id = idWithNamespace;
|
|
125
111
|
if (idWithNamespace.startsWith(this.namespaceObjects)) {
|
|
126
112
|
let idx = -1;
|
|
127
113
|
if (idWithNamespace.startsWith(this.namespaceObj)) {
|
|
128
114
|
idx = this.namespaceObjLen;
|
|
129
|
-
}
|
|
115
|
+
}
|
|
116
|
+
else if (idWithNamespace.startsWith(this.namespaceFile)) {
|
|
130
117
|
idx = this.namespaceFileLen;
|
|
131
|
-
}
|
|
118
|
+
}
|
|
119
|
+
else if (idWithNamespace.startsWith(this.namespaceSet)) {
|
|
132
120
|
idx = this.namespaceSetLen;
|
|
133
121
|
}
|
|
134
|
-
|
|
135
122
|
if (idx !== -1) {
|
|
136
123
|
ns = idWithNamespace.substr(0, idx);
|
|
137
124
|
id = idWithNamespace.substr(idx);
|
|
@@ -142,20 +129,23 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
142
129
|
id = fileIdDetails[1];
|
|
143
130
|
name = fileIdDetails[2] || '';
|
|
144
131
|
isMeta = fileIdDetails[3] === 'meta';
|
|
145
|
-
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
146
134
|
fileIdDetails = id.match(this.normalizeFileRegex2);
|
|
147
135
|
if (fileIdDetails) {
|
|
148
136
|
id = fileIdDetails[1];
|
|
149
137
|
name = fileIdDetails[2] || '';
|
|
150
138
|
isMeta = undefined;
|
|
151
|
-
}
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
152
141
|
name = '';
|
|
153
142
|
isMeta = undefined;
|
|
154
143
|
}
|
|
155
144
|
}
|
|
156
145
|
}
|
|
157
|
-
}
|
|
158
|
-
|
|
146
|
+
}
|
|
147
|
+
else if (idWithNamespace.startsWith(this.namespaceMeta)) {
|
|
148
|
+
const idx = this.namespaceMetaLen;
|
|
159
149
|
if (idx !== -1) {
|
|
160
150
|
ns = idWithNamespace.substr(0, idx);
|
|
161
151
|
id = idWithNamespace.substr(idx);
|
|
@@ -164,32 +154,37 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
164
154
|
}
|
|
165
155
|
return { id, namespace: ns, name, isMeta };
|
|
166
156
|
}
|
|
167
|
-
|
|
168
157
|
/**
|
|
169
158
|
* Publish a subscribed value to one of the redis connections in redis format
|
|
170
159
|
* @param client Instance of RedisHandler
|
|
171
160
|
* @param type Type of subscribed key
|
|
172
161
|
* @param id Subscribed ID
|
|
173
162
|
* @param obj Object to publish
|
|
174
|
-
* @returns {number} Publish counter 0 or 1 depending if send out or not
|
|
163
|
+
* @returns {number} Publish counter 0 or 1 depending on if send out or not
|
|
175
164
|
*/
|
|
176
165
|
publishToClients(client, type, id, obj) {
|
|
177
166
|
if (!client._subscribe || !client._subscribe[type]) {
|
|
178
167
|
return 0;
|
|
179
168
|
}
|
|
180
169
|
const s = client._subscribe[type];
|
|
181
|
-
|
|
182
170
|
const found = s.find(sub => sub.regex.test(id));
|
|
183
|
-
|
|
184
171
|
if (found) {
|
|
185
172
|
if (type === 'meta') {
|
|
186
173
|
this.log.silly(`${this.namespace} Redis Publish Meta ${id}=${obj}`);
|
|
187
|
-
const sendPattern = this.
|
|
188
|
-
const sendId = this.
|
|
174
|
+
const sendPattern = this.namespaceMeta + found.pattern;
|
|
175
|
+
const sendId = this.namespaceMeta + id;
|
|
189
176
|
client.sendArray(null, ['pmessage', sendPattern, sendId, obj]);
|
|
190
|
-
}
|
|
177
|
+
}
|
|
178
|
+
else if (type === 'files') {
|
|
191
179
|
const objString = JSON.stringify(obj);
|
|
192
|
-
this.log.silly(this.namespace
|
|
180
|
+
this.log.silly(`${this.namespace} Redis Publish File ${id}=${objString}`);
|
|
181
|
+
const sendPattern = this.namespaceFile + found.pattern;
|
|
182
|
+
const sendId = this.namespaceFile + id;
|
|
183
|
+
client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
const objString = JSON.stringify(obj);
|
|
187
|
+
this.log.silly(`${this.namespace} Redis Publish Object ${id}=${objString}`);
|
|
193
188
|
const sendPattern = (type === 'objects' ? '' : this.namespaceObjects) + found.pattern;
|
|
194
189
|
const sendId = (type === 'objects' ? this.namespaceObj : this.namespaceObjects) + id;
|
|
195
190
|
client.sendArray(null, ['pmessage', sendPattern, sendId, objString]);
|
|
@@ -198,7 +193,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
198
193
|
}
|
|
199
194
|
return 0;
|
|
200
195
|
}
|
|
201
|
-
|
|
202
196
|
/**
|
|
203
197
|
* Generate ID for a File
|
|
204
198
|
* @param id ID of the File
|
|
@@ -211,15 +205,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
211
205
|
if (id.endsWith('.admin')) {
|
|
212
206
|
if (name.startsWith('admin/')) {
|
|
213
207
|
name = name.replace(/^admin\//, '');
|
|
214
|
-
}
|
|
208
|
+
}
|
|
209
|
+
else if (name.match(/^iobroker.[-\d\w]\/admin\//i)) {
|
|
215
210
|
// e.g. ekey.admin and iobroker.ekey/admin/ekey.png
|
|
216
211
|
name = name.replace(/^iobroker.[-\d\w]\/admin\//i, '');
|
|
217
212
|
}
|
|
218
213
|
}
|
|
219
|
-
|
|
220
214
|
return this.namespaceFile + id + '$%$' + name + (isMeta !== undefined ? (isMeta ? '$%$meta' : '$%$data') : '');
|
|
221
215
|
}
|
|
222
|
-
|
|
223
216
|
/**
|
|
224
217
|
* Register all event listeners for Handler and implement the relevant logic
|
|
225
218
|
* @param handler RedisHandler instance
|
|
@@ -228,7 +221,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
228
221
|
_socketEvents(handler) {
|
|
229
222
|
let connectionName = null;
|
|
230
223
|
let namespaceLog = this.namespace;
|
|
231
|
-
|
|
232
224
|
// Handle Redis "INFO" request
|
|
233
225
|
handler.on('info', (_data, responseId) => {
|
|
234
226
|
let infoString = '# Server\r\n';
|
|
@@ -241,17 +233,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
241
233
|
infoString += '# CPU\r\n';
|
|
242
234
|
infoString += '# Cluster\r\n';
|
|
243
235
|
infoString += '# Keyspace\r\n';
|
|
244
|
-
infoString +=
|
|
236
|
+
infoString += `db0:keys=${Object.keys(this.dataset).length},expires=0,avg_ttl=98633637897`;
|
|
245
237
|
handler.sendBulk(responseId, infoString);
|
|
246
238
|
});
|
|
247
|
-
|
|
248
239
|
// Handle Redis "QUIT" request
|
|
249
240
|
handler.on('quit', (_data, responseId) => {
|
|
250
241
|
this.log.silly(namespaceLog + ' Redis QUIT received, close connection');
|
|
251
242
|
handler.sendString(responseId, 'OK');
|
|
252
243
|
handler.close();
|
|
253
244
|
});
|
|
254
|
-
|
|
255
245
|
// Handle Redis "SCRIPT" request
|
|
256
246
|
handler.on('script', (data, responseId) => {
|
|
257
247
|
data[0] = data[0].toLowerCase();
|
|
@@ -260,12 +250,12 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
260
250
|
const scripts = [];
|
|
261
251
|
data.forEach(checksum => scripts.push(this.knownScripts[checksum] ? 1 : 0));
|
|
262
252
|
handler.sendArray(responseId, scripts);
|
|
263
|
-
}
|
|
253
|
+
}
|
|
254
|
+
else if (data[0] === 'load') {
|
|
264
255
|
const shasum = crypto.createHash('sha1');
|
|
265
256
|
const buf = Buffer.from(data[1]);
|
|
266
257
|
shasum.update(buf);
|
|
267
258
|
const scriptChecksum = shasum.digest('hex');
|
|
268
|
-
|
|
269
259
|
const scriptDesign = data[1].match(/^-- design: ([a-z0-9A-Z-.]+)\s/m);
|
|
270
260
|
const scriptFunc = data[1].match(/^-- func: (.+)$/m);
|
|
271
261
|
if (scriptDesign && scriptDesign[1]) {
|
|
@@ -275,45 +265,35 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
275
265
|
if (scriptSearch && scriptSearch[1]) {
|
|
276
266
|
search = scriptSearch[1];
|
|
277
267
|
}
|
|
278
|
-
|
|
279
268
|
this.knownScripts[scriptChecksum] = { design: design, search: search };
|
|
280
269
|
if (this.settings.connection.enhancedLogging) {
|
|
281
|
-
this.log.silly(
|
|
282
|
-
`${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(
|
|
283
|
-
this.knownScripts[scriptChecksum]
|
|
284
|
-
)}`
|
|
285
|
-
);
|
|
270
|
+
this.log.silly(`${namespaceLog} Register View LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
|
|
286
271
|
}
|
|
287
272
|
handler.sendBulk(responseId, scriptChecksum);
|
|
288
|
-
}
|
|
273
|
+
}
|
|
274
|
+
else if (scriptFunc && scriptFunc[1]) {
|
|
289
275
|
this.knownScripts[scriptChecksum] = { func: scriptFunc[1] };
|
|
290
276
|
if (this.settings.connection.enhancedLogging) {
|
|
291
|
-
this.log.silly(
|
|
292
|
-
`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(
|
|
293
|
-
this.knownScripts[scriptChecksum]
|
|
294
|
-
)}`
|
|
295
|
-
);
|
|
277
|
+
this.log.silly(`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
|
|
296
278
|
}
|
|
297
279
|
handler.sendBulk(responseId, scriptChecksum);
|
|
298
|
-
}
|
|
280
|
+
}
|
|
281
|
+
else if (data[1].includes('-- REDLOCK SCRIPT')) {
|
|
299
282
|
// redlock scripts are currently not needed for Simulator
|
|
300
283
|
this.knownScripts[scriptChecksum] = { redlock: true };
|
|
301
284
|
if (this.settings.connection.enhancedLogging) {
|
|
302
|
-
this.log.silly(
|
|
303
|
-
`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(
|
|
304
|
-
this.knownScripts[scriptChecksum]
|
|
305
|
-
)}`
|
|
306
|
-
);
|
|
285
|
+
this.log.silly(`${namespaceLog} Register Func LUA Script: ${scriptChecksum} = ${JSON.stringify(this.knownScripts[scriptChecksum])}`);
|
|
307
286
|
}
|
|
308
287
|
handler.sendBulk(responseId, scriptChecksum);
|
|
309
|
-
}
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
310
290
|
handler.sendError(responseId, new Error(`Unknown LUA script ${data[1]}`));
|
|
311
291
|
}
|
|
312
|
-
}
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
313
294
|
handler.sendError(responseId, new Error(`Unsupported Script command ${data[0]}`));
|
|
314
295
|
}
|
|
315
296
|
});
|
|
316
|
-
|
|
317
297
|
// Handle Redis "EVALSHA" request
|
|
318
298
|
handler.on('evalsha', (data, responseId) => {
|
|
319
299
|
if (!this.knownScripts[data[0]]) {
|
|
@@ -330,9 +310,7 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
330
310
|
scriptSearch = 'state';
|
|
331
311
|
}
|
|
332
312
|
if (this.settings.connection.enhancedLogging) {
|
|
333
|
-
this.log.silly(
|
|
334
|
-
`${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`
|
|
335
|
-
);
|
|
313
|
+
this.log.silly(`${namespaceLog} Script transformed into getObjectView: design=${scriptDesign}, search=${scriptSearch}`);
|
|
336
314
|
}
|
|
337
315
|
let objs;
|
|
338
316
|
try {
|
|
@@ -341,18 +319,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
341
319
|
endkey: data[4],
|
|
342
320
|
include_docs: true
|
|
343
321
|
});
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
new Error(
|
|
348
|
-
'_getObjectView Error for ' + scriptDesign + '/' + scriptSearch + ': ' + err.message
|
|
349
|
-
)
|
|
350
|
-
);
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
return void handler.sendError(responseId, new Error(`_getObjectView Error for ${scriptDesign}/${scriptSearch}: ${err.message}`));
|
|
351
325
|
}
|
|
352
326
|
const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));
|
|
353
327
|
handler.sendArray(responseId, res);
|
|
354
328
|
}
|
|
355
|
-
}
|
|
329
|
+
}
|
|
330
|
+
else if (this.knownScripts[data[0]].func && data.length > 4) {
|
|
356
331
|
const scriptFunc = { map: this.knownScripts[data[0]].func.replace('%1', data[5]) };
|
|
357
332
|
if (this.settings.connection.enhancedLogging) {
|
|
358
333
|
this.log.silly(`${namespaceLog} Script transformed into _applyView: func=${scriptFunc.map}`);
|
|
@@ -363,44 +338,41 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
363
338
|
include_docs: true
|
|
364
339
|
});
|
|
365
340
|
const res = objs.rows.map(obj => JSON.stringify(this.dataset[obj.value._id || obj.id]));
|
|
366
|
-
|
|
367
341
|
return void handler.sendArray(responseId, res);
|
|
368
|
-
}
|
|
342
|
+
}
|
|
343
|
+
else if (this.knownScripts[data[0]].redlock) {
|
|
369
344
|
// just return a dummy
|
|
370
345
|
return void handler.sendArray(responseId, [0]);
|
|
371
|
-
}
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
372
348
|
handler.sendError(responseId, new Error(`Unknown LUA script eval call ${JSON.stringify(data)}`));
|
|
373
349
|
}
|
|
374
350
|
});
|
|
375
|
-
|
|
376
351
|
// Handle Redis "PUBLISH" request
|
|
377
352
|
handler.on('publish', (data, responseId) => {
|
|
378
353
|
const { id, namespace } = this._normalizeId(data[0]);
|
|
379
|
-
|
|
380
|
-
|
|
354
|
+
if (namespace === this.namespaceObj ||
|
|
355
|
+
namespace === this.namespaceMeta ||
|
|
356
|
+
namespace === this.namespaceFile) {
|
|
381
357
|
// a "set" always comes afterwards, so do not publish
|
|
382
358
|
return void handler.sendInteger(responseId, 0); // do not publish for now
|
|
383
359
|
}
|
|
384
360
|
const publishCount = this.publishAll(namespace.substr(0, namespace.length - 1), id, JSON.parse(data[1]));
|
|
385
361
|
handler.sendInteger(responseId, publishCount);
|
|
386
362
|
});
|
|
387
|
-
|
|
388
363
|
// Handle Redis "MGET" requests
|
|
389
364
|
handler.on('mget', (data, responseId) => {
|
|
390
365
|
if (!data || !data.length) {
|
|
391
366
|
return void handler.sendArray(responseId, []);
|
|
392
367
|
}
|
|
393
368
|
const { namespace, isMeta } = this._normalizeId(data[0]);
|
|
394
|
-
|
|
395
369
|
if (namespace === this.namespaceObj) {
|
|
396
370
|
const keys = [];
|
|
397
371
|
data.forEach(dataId => {
|
|
398
372
|
const { id, namespace } = this._normalizeId(dataId);
|
|
399
373
|
if (namespace !== this.namespaceObj) {
|
|
400
374
|
keys.push(null);
|
|
401
|
-
this.log.warn(
|
|
402
|
-
`${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`
|
|
403
|
-
);
|
|
375
|
+
this.log.warn(`${namespaceLog} Got MGET request for non Object-ID in Objects-ID chunk for ${namespace} / ${dataId}`);
|
|
404
376
|
return;
|
|
405
377
|
}
|
|
406
378
|
keys.push(id);
|
|
@@ -408,12 +380,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
408
380
|
let result;
|
|
409
381
|
try {
|
|
410
382
|
result = this._getObjects(keys);
|
|
411
|
-
}
|
|
383
|
+
}
|
|
384
|
+
catch (err) {
|
|
412
385
|
return void handler.sendError(responseId, new Error('ERROR _getObjects: ' + err.message));
|
|
413
386
|
}
|
|
414
387
|
result = result.map(el => (el ? JSON.stringify(el) : null));
|
|
415
388
|
handler.sendArray(responseId, result);
|
|
416
|
-
}
|
|
389
|
+
}
|
|
390
|
+
else if (namespace === this.namespaceFile) {
|
|
417
391
|
// Handle request for Meta data for files
|
|
418
392
|
if (isMeta) {
|
|
419
393
|
const response = [];
|
|
@@ -421,9 +395,7 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
421
395
|
const { id, namespace, name } = this._normalizeId(dataId);
|
|
422
396
|
if (namespace !== this.namespaceFile) {
|
|
423
397
|
response.push(null);
|
|
424
|
-
this.log.warn(
|
|
425
|
-
`${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`
|
|
426
|
-
);
|
|
398
|
+
this.log.warn(`${namespaceLog} Got MGET request for non File ID in File-ID chunk for ${dataId}`);
|
|
427
399
|
return;
|
|
428
400
|
}
|
|
429
401
|
this._loadFileSettings(id);
|
|
@@ -435,11 +407,10 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
435
407
|
try {
|
|
436
408
|
// @ts-ignore
|
|
437
409
|
obj.stats = fs.statSync(path.join(this.objectsDir, id, name));
|
|
438
|
-
}
|
|
410
|
+
}
|
|
411
|
+
catch (err) {
|
|
439
412
|
if (!name.endsWith('/_data.json')) {
|
|
440
|
-
this.log.warn(
|
|
441
|
-
`${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`
|
|
442
|
-
);
|
|
413
|
+
this.log.warn(`${namespaceLog} Got MGET request for non existing file ${dataId}, err: ${err.message}`);
|
|
443
414
|
}
|
|
444
415
|
response.push(null);
|
|
445
416
|
return;
|
|
@@ -447,65 +418,58 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
447
418
|
response.push(JSON.stringify(obj));
|
|
448
419
|
});
|
|
449
420
|
handler.sendArray(responseId, response);
|
|
450
|
-
}
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
451
423
|
// Handle request for File data
|
|
452
424
|
handler.sendError(responseId, new Error('MGET-UNSUPPORTED for file data'));
|
|
453
425
|
}
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
new Error('MGET-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
|
|
458
|
-
);
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
handler.sendError(responseId, new Error(`MGET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
459
429
|
}
|
|
460
430
|
});
|
|
461
|
-
|
|
462
431
|
// Handle Redis "GET" requests
|
|
463
432
|
handler.on('get', (data, responseId) => {
|
|
464
433
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
465
|
-
|
|
466
434
|
if (namespace === this.namespaceObj) {
|
|
467
435
|
const result = this._getObject(id);
|
|
468
436
|
if (!result) {
|
|
469
437
|
handler.sendNull(responseId);
|
|
470
|
-
}
|
|
438
|
+
}
|
|
439
|
+
else {
|
|
471
440
|
handler.sendBulk(responseId, JSON.stringify(result));
|
|
472
441
|
}
|
|
473
|
-
}
|
|
442
|
+
}
|
|
443
|
+
else if (namespace === this.namespaceFile) {
|
|
474
444
|
// Handle request for Meta data for files
|
|
475
445
|
if (isMeta) {
|
|
476
446
|
let stats;
|
|
477
447
|
try {
|
|
478
448
|
stats = fs.statSync(path.join(this.objectsDir, id, name));
|
|
479
|
-
}
|
|
449
|
+
}
|
|
450
|
+
catch {
|
|
480
451
|
return void handler.sendNull(responseId);
|
|
481
452
|
}
|
|
482
453
|
if (stats.isDirectory()) {
|
|
483
|
-
return void handler.sendBulk(
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
isDir: true
|
|
489
|
-
})
|
|
490
|
-
);
|
|
454
|
+
return void handler.sendBulk(responseId, JSON.stringify({
|
|
455
|
+
file: name,
|
|
456
|
+
stats: {},
|
|
457
|
+
isDir: true
|
|
458
|
+
}));
|
|
491
459
|
}
|
|
492
460
|
this._loadFileSettings(id);
|
|
493
461
|
if (!this.fileOptions[id] || !this.fileOptions[id][name]) {
|
|
494
462
|
return void handler.sendNull(responseId);
|
|
495
463
|
}
|
|
496
|
-
|
|
497
464
|
let obj = this._clone(this.fileOptions[id][name]);
|
|
498
465
|
if (typeof obj !== 'object') {
|
|
499
466
|
obj = {
|
|
500
467
|
mimeType: obj,
|
|
501
468
|
acl: {
|
|
502
|
-
owner:
|
|
503
|
-
|
|
504
|
-
ownerGroup:
|
|
505
|
-
(this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
|
|
469
|
+
owner: (this.defaultNewAcl && this.defaultNewAcl.owner) || utils.CONSTS.SYSTEM_ADMIN_USER,
|
|
470
|
+
ownerGroup: (this.defaultNewAcl && this.defaultNewAcl.ownerGroup) ||
|
|
506
471
|
utils.CONSTS.SYSTEM_ADMIN_GROUP,
|
|
507
|
-
permissions:
|
|
508
|
-
(this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
|
|
472
|
+
permissions: (this.defaultNewAcl && this.defaultNewAcl.file.permissions) ||
|
|
509
473
|
utils.CONSTS.ACCESS_USER_ALL |
|
|
510
474
|
utils.CONSTS.ACCESS_GROUP_ALL |
|
|
511
475
|
utils.CONSTS.ACCESS_EVERY_ALL // 777
|
|
@@ -514,12 +478,14 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
514
478
|
}
|
|
515
479
|
obj.stats = stats;
|
|
516
480
|
handler.sendBulk(responseId, JSON.stringify(obj));
|
|
517
|
-
}
|
|
481
|
+
}
|
|
482
|
+
else {
|
|
518
483
|
// Handle request for File data
|
|
519
484
|
let data;
|
|
520
485
|
try {
|
|
521
486
|
data = this._readFile(id, name);
|
|
522
|
-
}
|
|
487
|
+
}
|
|
488
|
+
catch {
|
|
523
489
|
return void handler.sendNull(responseId);
|
|
524
490
|
}
|
|
525
491
|
if (data.fileContent === undefined || data.fileContent === null) {
|
|
@@ -529,308 +495,290 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
529
495
|
if (!Buffer.isBuffer(fileData) && tools.isObject(fileData)) {
|
|
530
496
|
// if its an invalid object, stringify it and log warning
|
|
531
497
|
fileData = JSON.stringify(fileData);
|
|
532
|
-
this.log.warn(
|
|
533
|
-
`${namespaceLog} Data of "${id}/${name}" has invalid structure at file data request: ${fileData}`
|
|
534
|
-
);
|
|
498
|
+
this.log.warn(`${namespaceLog} Data of "${id}/${name}" has invalid structure at file data request: ${fileData}`);
|
|
535
499
|
}
|
|
536
500
|
handler.sendBufBulk(responseId, Buffer.from(fileData));
|
|
537
501
|
}
|
|
538
|
-
}
|
|
502
|
+
}
|
|
503
|
+
else if (namespace === this.namespaceMeta) {
|
|
539
504
|
// special handling for the primaryHost
|
|
540
505
|
if (id === 'objects.primaryHost') {
|
|
541
506
|
// we are the server -> we are primary
|
|
542
507
|
handler.sendString(this.settings.hostname);
|
|
543
|
-
}
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
544
510
|
const result = this.getMeta(id);
|
|
545
511
|
if (result === undefined || result === null) {
|
|
546
512
|
handler.sendNull(responseId);
|
|
547
|
-
}
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
548
515
|
handler.sendBulk(responseId, result);
|
|
549
516
|
}
|
|
550
517
|
}
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
new Error('GET-UNSUPPORTED for namespace ' + namespace + ': Data=' + JSON.stringify(data))
|
|
555
|
-
);
|
|
518
|
+
}
|
|
519
|
+
else {
|
|
520
|
+
handler.sendError(responseId, new Error(`GET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
556
521
|
}
|
|
557
522
|
});
|
|
558
|
-
|
|
559
523
|
// Handle Redis "SET" requests
|
|
560
524
|
handler.on('set', (data, responseId) => {
|
|
561
525
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
562
|
-
|
|
563
526
|
if (namespace === this.namespaceObj) {
|
|
564
527
|
try {
|
|
565
528
|
const obj = JSON.parse(data[1].toString('utf-8'));
|
|
566
529
|
this._setObjectDirect(id, obj);
|
|
567
|
-
}
|
|
530
|
+
}
|
|
531
|
+
catch (err) {
|
|
568
532
|
return void handler.sendError(responseId, new Error(`ERROR setObject id=${id}: ${err.message}`));
|
|
569
533
|
}
|
|
570
534
|
handler.sendString(responseId, 'OK');
|
|
571
|
-
}
|
|
572
|
-
|
|
535
|
+
}
|
|
536
|
+
else if (namespace === this.namespaceFile) {
|
|
537
|
+
// Handle request to set meta-data, we ignore it because
|
|
573
538
|
// will be set when data are written
|
|
574
539
|
if (isMeta) {
|
|
575
540
|
this._loadFileSettings(id);
|
|
576
|
-
|
|
577
541
|
try {
|
|
578
542
|
fs.ensureDirSync(path.join(this.objectsDir, id, path.dirname(name)));
|
|
579
|
-
|
|
580
|
-
// only set if the meta object is already/still existing
|
|
543
|
+
// only set if the meta-object is already/still existing
|
|
581
544
|
if (this.fileOptions[id]) {
|
|
582
545
|
this.fileOptions[id][name] = JSON.parse(data[1].toString('utf-8'));
|
|
583
|
-
fs.writeFileSync(
|
|
584
|
-
path.join(this.objectsDir, id, '_data.json'),
|
|
585
|
-
JSON.stringify(this.fileOptions[id])
|
|
586
|
-
);
|
|
546
|
+
fs.writeFileSync(path.join(this.objectsDir, id, '_data.json'), JSON.stringify(this.fileOptions[id]));
|
|
587
547
|
}
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`)
|
|
592
|
-
);
|
|
548
|
+
}
|
|
549
|
+
catch (err) {
|
|
550
|
+
return void handler.sendError(responseId, new Error(`ERROR writeFile-Meta id=${id}: ${err.message}`));
|
|
593
551
|
}
|
|
594
552
|
handler.sendString(responseId, 'OK');
|
|
595
|
-
}
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
596
555
|
// Handle request to write the file
|
|
597
556
|
try {
|
|
598
557
|
this._writeFile(id, name, data[1]);
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
new Error(`ERROR writeFile id=${id}: ${err.message}`)
|
|
603
|
-
);
|
|
558
|
+
}
|
|
559
|
+
catch (err) {
|
|
560
|
+
return void handler.sendError(responseId, new Error(`ERROR writeFile id=${id}: ${err.message}`));
|
|
604
561
|
}
|
|
605
562
|
handler.sendString(responseId, 'OK');
|
|
606
563
|
}
|
|
607
|
-
}
|
|
564
|
+
}
|
|
565
|
+
else if (namespace === this.namespaceMeta) {
|
|
608
566
|
this.setMeta(id, data[1].toString('utf-8'));
|
|
609
567
|
handler.sendString(responseId, 'OK');
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`)
|
|
614
|
-
);
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
handler.sendError(responseId, new Error(`SET-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
615
571
|
}
|
|
616
572
|
});
|
|
617
|
-
|
|
618
573
|
// Handle Redis "RENAME" requests
|
|
619
574
|
handler.on('rename', (data, responseId) => {
|
|
620
575
|
const oldDetails = this._normalizeId(data[0]);
|
|
621
576
|
const newDetails = this._normalizeId(data[1]);
|
|
622
|
-
|
|
623
577
|
if (oldDetails.namespace === this.namespaceFile) {
|
|
624
578
|
if (oldDetails.id !== newDetails.id) {
|
|
625
|
-
return void handler.sendError(
|
|
626
|
-
responseId,
|
|
627
|
-
new Error('ERROR renameObject: id needs to stay the same')
|
|
628
|
-
);
|
|
579
|
+
return void handler.sendError(responseId, new Error('ERROR renameObject: id needs to stay the same'));
|
|
629
580
|
}
|
|
630
|
-
|
|
631
581
|
// Handle request for Meta data for files
|
|
632
582
|
if (oldDetails.isMeta) {
|
|
633
583
|
handler.sendString(responseId, 'OK');
|
|
634
|
-
}
|
|
584
|
+
}
|
|
585
|
+
else {
|
|
635
586
|
// Handle request for File data
|
|
636
587
|
try {
|
|
637
588
|
this._rename(oldDetails.id, oldDetails.name, newDetails.name);
|
|
638
|
-
}
|
|
589
|
+
}
|
|
590
|
+
catch {
|
|
639
591
|
return void handler.sendNull(responseId);
|
|
640
592
|
}
|
|
641
593
|
handler.sendString(responseId, 'OK');
|
|
642
594
|
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`)
|
|
647
|
-
);
|
|
595
|
+
}
|
|
596
|
+
else {
|
|
597
|
+
handler.sendError(responseId, new Error(`RENAME-UNSUPPORTED for namespace ${oldDetails.namespace}: Data=${JSON.stringify(data)}`));
|
|
648
598
|
}
|
|
649
599
|
});
|
|
650
|
-
|
|
651
600
|
// Handle Redis "DEL" request for state and session namespace
|
|
652
601
|
handler.on('del', (data, responseId) => {
|
|
653
602
|
const { id, namespace, name, isMeta } = this._normalizeId(data[0]);
|
|
654
|
-
|
|
655
603
|
if (namespace === this.namespaceObj) {
|
|
656
604
|
try {
|
|
657
605
|
this._delObject(id);
|
|
658
|
-
}
|
|
606
|
+
}
|
|
607
|
+
catch (err) {
|
|
659
608
|
return void handler.sendError(responseId, err);
|
|
660
609
|
}
|
|
661
610
|
handler.sendInteger(responseId, 1);
|
|
662
|
-
}
|
|
663
|
-
|
|
611
|
+
}
|
|
612
|
+
else if (namespace === this.namespaceFile) {
|
|
613
|
+
// Handle request to delete meta-data, we ignore it because
|
|
664
614
|
// will be removed when data are deleted
|
|
665
615
|
if (isMeta) {
|
|
666
616
|
handler.sendString(responseId, 'OK');
|
|
667
|
-
}
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
668
619
|
// Handle request to remove the file
|
|
669
620
|
try {
|
|
670
621
|
this._unlink(id, name);
|
|
671
|
-
}
|
|
622
|
+
}
|
|
623
|
+
catch (err) {
|
|
672
624
|
return void handler.sendError(responseId, err);
|
|
673
625
|
}
|
|
674
626
|
handler.sendString(responseId, 'OK');
|
|
675
627
|
}
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`)
|
|
680
|
-
);
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
handler.sendError(responseId, new Error(`DEL-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
681
631
|
}
|
|
682
632
|
});
|
|
683
|
-
|
|
684
633
|
handler.on('exists', (data, responseId) => {
|
|
685
634
|
if (!data || !data.length) {
|
|
686
635
|
return void handler.sendInteger(responseId, 0);
|
|
687
636
|
}
|
|
688
|
-
|
|
689
637
|
// Note: we only simulate single key existence check
|
|
690
638
|
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
691
|
-
|
|
692
639
|
if (namespace === this.namespaceObj) {
|
|
693
640
|
let exists;
|
|
694
641
|
try {
|
|
695
642
|
exists = this._objectExists(id);
|
|
696
|
-
}
|
|
643
|
+
}
|
|
644
|
+
catch (e) {
|
|
697
645
|
return void handler.sendError(responseId, e);
|
|
698
646
|
}
|
|
699
647
|
handler.sendInteger(responseId, exists ? 1 : 0);
|
|
700
|
-
}
|
|
648
|
+
}
|
|
649
|
+
else if (namespace === this.namespaceFile) {
|
|
701
650
|
let exists;
|
|
702
651
|
try {
|
|
703
652
|
exists = this._fileExists(id, name);
|
|
704
|
-
}
|
|
653
|
+
}
|
|
654
|
+
catch (e) {
|
|
705
655
|
return void handler.sendError(responseId, e);
|
|
706
656
|
}
|
|
707
657
|
handler.sendInteger(responseId, exists ? 1 : 0);
|
|
708
|
-
}
|
|
658
|
+
}
|
|
659
|
+
else if (namespace === this.namespaceSet) {
|
|
709
660
|
// we are not using sets in simulator, so just say it exists
|
|
710
661
|
return void handler.sendInteger(responseId, 1);
|
|
711
|
-
}
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
712
664
|
handler.sendError(responseId, new Error(`EXISTS-UNSUPPORTED for namespace ${namespace}`));
|
|
713
665
|
}
|
|
714
666
|
});
|
|
715
|
-
|
|
716
667
|
// handle Redis "SCAN" request for objects namespace
|
|
717
668
|
handler.on('scan', (data, responseId) => {
|
|
718
669
|
if (!data || data.length < 3) {
|
|
719
670
|
return void handler.sendArray(responseId, ['0', []]);
|
|
720
671
|
}
|
|
721
|
-
|
|
722
672
|
return this._handleScanOrKeys(handler, data[2], responseId, true);
|
|
723
673
|
});
|
|
724
|
-
|
|
725
674
|
// Handle Redis "KEYS" request for state namespace
|
|
726
675
|
handler.on('keys', (data, responseId) => {
|
|
727
676
|
if (!data || !data.length) {
|
|
728
677
|
return void handler.sendArray(responseId, []);
|
|
729
678
|
}
|
|
730
|
-
|
|
731
679
|
return this._handleScanOrKeys(handler, data[0], responseId);
|
|
732
680
|
});
|
|
733
|
-
|
|
734
681
|
// commands for redis SETS, just dummies
|
|
735
682
|
handler.on('sadd', (data, responseId) => {
|
|
736
683
|
return void handler.sendInteger(responseId, 1);
|
|
737
684
|
});
|
|
738
|
-
|
|
739
685
|
handler.on('srem', (data, responseId) => {
|
|
740
686
|
return void handler.sendInteger(responseId, 1);
|
|
741
687
|
});
|
|
742
|
-
|
|
743
688
|
handler.on('sscan', (data, responseId) => {
|
|
744
689
|
// for file DB it does the same as scan but data looks different
|
|
745
690
|
if (!data || data.length < 4) {
|
|
746
691
|
return void handler.sendArray(responseId, ['0', []]);
|
|
747
692
|
}
|
|
748
|
-
|
|
749
693
|
return this._handleScanOrKeys(handler, data[3], responseId, true);
|
|
750
694
|
});
|
|
751
|
-
|
|
752
695
|
// Handle Redis "PSUBSCRIBE" request for state, log and session namespace
|
|
753
696
|
handler.on('psubscribe', (data, responseId) => {
|
|
754
|
-
const { id, namespace } = this._normalizeId(data[0]);
|
|
755
|
-
|
|
697
|
+
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
756
698
|
if (namespace === this.namespaceObj) {
|
|
757
699
|
this._subscribeConfigForClient(handler, id);
|
|
758
700
|
handler.sendArray(responseId, ['psubscribe', data[0], 1]);
|
|
759
|
-
}
|
|
701
|
+
}
|
|
702
|
+
else if (namespace === this.namespaceMeta) {
|
|
760
703
|
this._subscribeMeta(handler, id);
|
|
761
704
|
handler.sendArray(responseId, ['psubscribe', data[0], 1]);
|
|
762
|
-
}
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
705
|
+
}
|
|
706
|
+
else if (namespace === this.namespaceFile) {
|
|
707
|
+
this._subscribeFileForClient(handler, id, name);
|
|
708
|
+
handler.sendArray(responseId, ['psubscribe', data[0], 1]);
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
handler.sendError(responseId, new Error(`PSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
767
712
|
}
|
|
768
713
|
});
|
|
769
|
-
|
|
770
714
|
// Handle Redis "UNSUBSCRIBE" request for state, log and session namespace
|
|
771
715
|
handler.on('punsubscribe', (data, responseId) => {
|
|
772
|
-
const { id, namespace } = this._normalizeId(data[0]);
|
|
773
|
-
|
|
716
|
+
const { id, namespace, name } = this._normalizeId(data[0]);
|
|
774
717
|
if (namespace === this.namespaceObj) {
|
|
775
718
|
this._unsubscribeConfigForClient(handler, id);
|
|
776
719
|
handler.sendArray(responseId, ['punsubscribe', data[0], 1]);
|
|
777
|
-
}
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
720
|
+
}
|
|
721
|
+
else if (namespace === this.namespaceFile) {
|
|
722
|
+
this._unsubscribeFileForClient(handler, id, name);
|
|
723
|
+
handler.sendArray(responseId, ['punsubscribe', data[0], 1]);
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
handler.sendError(responseId, new Error(`PUNSUBSCRIBE-UNSUPPORTED for namespace ${namespace}: Data=${JSON.stringify(data)}`));
|
|
782
727
|
}
|
|
783
728
|
});
|
|
784
|
-
|
|
785
729
|
// Handle Redis "SUBSCRIBE" ... currently mainly ignored
|
|
786
730
|
handler.on('subscribe', (data, responseId) => {
|
|
787
731
|
if (data[0].startsWith('__keyevent@')) {
|
|
788
732
|
// we ignore these type of events because we publish expires anyway directly
|
|
789
733
|
handler.sendArray(responseId, ['subscribe', data[0], 1]);
|
|
790
|
-
}
|
|
734
|
+
}
|
|
735
|
+
else {
|
|
791
736
|
handler.sendError(responseId, new Error(`SUBSCRIBE-UNSUPPORTED for ${data[0]}`));
|
|
792
737
|
}
|
|
793
738
|
});
|
|
794
|
-
|
|
795
739
|
// Handle Redis "CONFIG" ... currently mainly ignored
|
|
796
740
|
handler.on('config', (data, responseId) => {
|
|
797
|
-
|
|
741
|
+
const command = typeof data[0] === 'string' ? data[0].toLowerCase() : data[0].toString().toLowerCase();
|
|
742
|
+
if (command === 'set' && data[1] === 'notify-keyspace-events') {
|
|
798
743
|
// we ignore these type of commands for now, should only be to subscribe to keyspace events
|
|
799
744
|
handler.sendString(responseId, 'OK');
|
|
800
|
-
}
|
|
745
|
+
}
|
|
746
|
+
else if (command === 'set' && data[1] === 'lua-time-limit') {
|
|
801
747
|
// we ignore these type of commands for now, irrelevant
|
|
802
748
|
handler.sendString(responseId, 'OK');
|
|
803
|
-
}
|
|
749
|
+
}
|
|
750
|
+
else {
|
|
804
751
|
handler.sendError(responseId, new Error('CONFIG-UNSUPPORTED for ' + JSON.stringify(data)));
|
|
805
752
|
}
|
|
806
753
|
});
|
|
807
|
-
|
|
808
754
|
// handle client SETNAME/GETNAME
|
|
809
755
|
handler.on('client', (data, responseId) => {
|
|
810
756
|
if (data[0] === 'setname' && typeof data[1] === 'string') {
|
|
811
757
|
if (data[1] === '') {
|
|
812
758
|
// on empty string redis sets null again and sends 'OK'
|
|
813
759
|
connectionName = null;
|
|
814
|
-
}
|
|
760
|
+
}
|
|
761
|
+
else {
|
|
815
762
|
connectionName = data[1];
|
|
816
763
|
namespaceLog = connectionName;
|
|
817
764
|
}
|
|
818
765
|
handler.sendString(responseId, 'OK');
|
|
819
|
-
}
|
|
766
|
+
}
|
|
767
|
+
else if (data[0] === 'getname') {
|
|
820
768
|
if (typeof connectionName === 'string' && connectionName !== '') {
|
|
821
769
|
handler.sendString(responseId, connectionName);
|
|
822
|
-
}
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
823
772
|
// redis sends null if no name defined
|
|
824
773
|
handler.sendNull(responseId);
|
|
825
774
|
}
|
|
826
|
-
}
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
827
777
|
handler.sendError(responseId, new Error(`CLIENT-UNSUPPORTED for ${JSON.stringify(data)}`));
|
|
828
778
|
}
|
|
829
779
|
});
|
|
830
|
-
|
|
831
780
|
handler.on('error', err => this.log.warn(`${namespaceLog} Redis objects: ${err}`));
|
|
832
781
|
}
|
|
833
|
-
|
|
834
782
|
/**
|
|
835
783
|
* Return connected RedisHandlers/Connections
|
|
836
784
|
* @returns {{}|*}
|
|
@@ -838,7 +786,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
838
786
|
getClients() {
|
|
839
787
|
return this.serverConnections;
|
|
840
788
|
}
|
|
841
|
-
|
|
842
789
|
/**
|
|
843
790
|
* Destructor of the class. Called by shutting down.
|
|
844
791
|
*/
|
|
@@ -848,23 +795,21 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
848
795
|
this.serverConnections[s].close();
|
|
849
796
|
delete this.serverConnections[s];
|
|
850
797
|
});
|
|
851
|
-
|
|
852
798
|
await new Promise(resolve => {
|
|
853
799
|
if (!this.server) {
|
|
854
800
|
return void resolve();
|
|
855
801
|
}
|
|
856
802
|
try {
|
|
857
803
|
this.server.close(() => resolve());
|
|
858
|
-
}
|
|
804
|
+
}
|
|
805
|
+
catch (e) {
|
|
859
806
|
console.log(e.message);
|
|
860
807
|
resolve();
|
|
861
808
|
}
|
|
862
809
|
});
|
|
863
810
|
}
|
|
864
|
-
|
|
865
811
|
await super.destroy();
|
|
866
812
|
}
|
|
867
|
-
|
|
868
813
|
/**
|
|
869
814
|
* Get keys matching pattern and send it to given responseId, for "SCAN" and "KEYS" - Objects and files supported
|
|
870
815
|
*
|
|
@@ -876,7 +821,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
876
821
|
*/
|
|
877
822
|
_handleScanOrKeys(handler, pattern, responseId, isScan = false) {
|
|
878
823
|
const { id, namespace, name, isMeta } = this._normalizeId(pattern);
|
|
879
|
-
|
|
880
824
|
let response = [];
|
|
881
825
|
if (namespace === this.namespaceObj || namespace === this.namespaceObjects) {
|
|
882
826
|
response = this._getKeys(id).map(val => this.namespaceObj + val);
|
|
@@ -903,7 +847,8 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
903
847
|
}
|
|
904
848
|
];
|
|
905
849
|
}
|
|
906
|
-
}
|
|
850
|
+
}
|
|
851
|
+
catch (err) {
|
|
907
852
|
if (!err.message.endsWith(utils.ERRORS.ERROR_NOT_FOUND)) {
|
|
908
853
|
return void handler.sendError(responseId, new Error(`ERROR readDir id=${id}: ${err.message}`));
|
|
909
854
|
}
|
|
@@ -919,7 +864,8 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
919
864
|
if (entryId === '' || entryId === '*') {
|
|
920
865
|
entryId = arr.file;
|
|
921
866
|
arr.file = '_data.json'; // We return a "virtual file" to mark the directory as existing
|
|
922
|
-
}
|
|
867
|
+
}
|
|
868
|
+
else {
|
|
923
869
|
arr.file += '/_data.json'; // We return a "virtual file" to mark the directory as existing
|
|
924
870
|
}
|
|
925
871
|
}
|
|
@@ -928,20 +874,19 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
928
874
|
response.push(this.getFileId(entryId, baseName + arr.file, false));
|
|
929
875
|
});
|
|
930
876
|
handler.sendArray(responseId, isScan ? ['0', response] : response); // send out file or full db response
|
|
931
|
-
}
|
|
877
|
+
}
|
|
878
|
+
else {
|
|
932
879
|
// such a request should never happen
|
|
933
880
|
handler.sendArray(responseId, isScan ? ['0', []] : []); // send out file or full db response
|
|
934
881
|
}
|
|
935
|
-
}
|
|
882
|
+
}
|
|
883
|
+
else if (namespace === this.namespaceSet) {
|
|
936
884
|
handler.sendArray(responseId, isScan ? ['0', []] : []); // send out empty array, we have no sets
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`)
|
|
941
|
-
);
|
|
885
|
+
}
|
|
886
|
+
else {
|
|
887
|
+
handler.sendError(responseId, new Error(`${isScan ? 'SCAN' : 'KEYS'}-UNSUPPORTED for namespace ${namespace}: Pattern=${pattern}`));
|
|
942
888
|
}
|
|
943
889
|
}
|
|
944
|
-
|
|
945
890
|
/**
|
|
946
891
|
* Initialize RedisHandler for a new network connection
|
|
947
892
|
* @param socket Network socket
|
|
@@ -953,13 +898,12 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
953
898
|
}
|
|
954
899
|
const options = {
|
|
955
900
|
log: this.log,
|
|
956
|
-
logScope:
|
|
901
|
+
logScope: `${this.settings.namespace || ''} Objects`,
|
|
957
902
|
handleAsBuffers: true,
|
|
958
903
|
enhancedLogging: this.settings.connection.enhancedLogging
|
|
959
904
|
};
|
|
960
905
|
const handler = new RedisHandler(socket, options);
|
|
961
906
|
this._socketEvents(handler);
|
|
962
|
-
|
|
963
907
|
this.serverConnections[socket.remoteAddress + ':' + socket.remotePort] = handler;
|
|
964
908
|
socket.on('close', () => {
|
|
965
909
|
if (this.serverConnections[socket.remoteAddress + ':' + socket.remotePort]) {
|
|
@@ -967,7 +911,6 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
967
911
|
}
|
|
968
912
|
});
|
|
969
913
|
}
|
|
970
|
-
|
|
971
914
|
/**
|
|
972
915
|
* Initialize Redis Server
|
|
973
916
|
* @param settings Settings object
|
|
@@ -981,25 +924,15 @@ class ObjectsInMemoryServer extends ObjectsInMemoryFileDB {
|
|
|
981
924
|
}
|
|
982
925
|
try {
|
|
983
926
|
this.server = net.createServer();
|
|
984
|
-
this.server.on('error', err =>
|
|
985
|
-
this.log.info(
|
|
986
|
-
`${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${
|
|
987
|
-
settings.port || 9001
|
|
988
|
-
}: ${err}`
|
|
989
|
-
)
|
|
990
|
-
);
|
|
927
|
+
this.server.on('error', err => this.log.info(`${this.namespace} ${settings.secure ? 'Secure ' : ''} Error inMem-objects listening on port ${settings.port || 9001}: ${err}`));
|
|
991
928
|
this.server.on('connection', socket => this._initSocket(socket));
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
settings.host === 'localhost' ? '127.0.0.1' : settings.host ? settings.host : undefined,
|
|
996
|
-
() => resolve()
|
|
997
|
-
);
|
|
998
|
-
} catch (err) {
|
|
929
|
+
this.server.listen(settings.port || 9001, settings.host === 'localhost' ? '127.0.0.1' : settings.host ? settings.host : undefined, () => resolve());
|
|
930
|
+
}
|
|
931
|
+
catch (err) {
|
|
999
932
|
reject(err);
|
|
1000
933
|
}
|
|
1001
934
|
});
|
|
1002
935
|
}
|
|
1003
936
|
}
|
|
1004
|
-
|
|
1005
937
|
module.exports = ObjectsInMemoryServer;
|
|
938
|
+
//# sourceMappingURL=objectsInMemServerRedis.js.map
|