ueberdb2 4.1.23 → 4.1.26
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/cassandra_db.d.ts +1 -0
- package/dist/couch_db.d.ts +1 -0
- package/dist/databases/cassandra_db.cjs +1 -0
- package/dist/databases/couch_db.cjs +1 -0
- package/dist/databases/dirty_db.cjs +1 -0
- package/dist/databases/dirty_git_db.cjs +1 -0
- package/dist/databases/elasticsearch_db.cjs +1 -0
- package/dist/databases/memory_db.cjs +1 -0
- package/dist/databases/mock_db.cjs +1 -0
- package/dist/databases/mongodb_db.cjs +1 -0
- package/dist/databases/mssql_db.cjs +5 -0
- package/dist/databases/mysql_db.cjs +1 -0
- package/dist/databases/postgres_db.cjs +1 -0
- package/dist/databases/postgrespool_db.cjs +1 -0
- package/dist/databases/redis_db.cjs +1 -0
- package/dist/databases/rethink_db.cjs +1 -0
- package/dist/databases/sqlite_db.cjs +4 -0
- package/dist/dirty_db.d.ts +1 -0
- package/dist/dirty_git_db.d.ts +1 -0
- package/dist/elasticsearch_db.d.ts +1 -0
- package/dist/index.d.ts +85 -0
- package/dist/lib/AbstractDatabase.cjs +1 -0
- package/dist/lib/CacheAndBufferLayer.cjs +1 -0
- package/dist/lib/logging.cjs +1 -0
- package/dist/memory_db.d.ts +1 -0
- package/dist/mock_db.d.ts +1 -0
- package/dist/mongodb_db.d.ts +1 -0
- package/dist/mssql_db.d.ts +1 -0
- package/dist/mysql_db.d.ts +1 -0
- package/dist/postgres_db.d.ts +1 -0
- package/dist/postgrespool_db.d.ts +1 -0
- package/dist/redis_db.d.ts +1 -0
- package/dist/rethink_db.d.ts +1 -0
- package/dist/sqlite_db.d.ts +1 -0
- package/package.json +7 -6
- package/dist/databases/cassandra_db.js +0 -235
- package/dist/databases/couch_db.js +0 -173
- package/dist/databases/dirty_db.js +0 -75
- package/dist/databases/dirty_git_db.js +0 -59
- package/dist/databases/elasticsearch_db.js +0 -243
- package/dist/databases/memory_db.js +0 -37
- package/dist/databases/mock_db.js +0 -41
- package/dist/databases/mongodb_db.js +0 -134
- package/dist/databases/mssql_db.js +0 -185
- package/dist/databases/mysql_db.js +0 -167
- package/dist/databases/postgres_db.js +0 -190
- package/dist/databases/postgrespool_db.js +0 -12
- package/dist/databases/redis_db.js +0 -120
- package/dist/databases/rethink_db.js +0 -121
- package/dist/databases/sqlite_db.js +0 -138
- package/dist/index.js +0 -193
- package/dist/lib/AbstractDatabase.js +0 -40
- package/dist/lib/CacheAndBufferLayer.js +0 -658
- package/dist/lib/logging.js +0 -27
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AbstractDatabase = require('../lib/AbstractDatabase.js');
|
|
4
|
-
var http = require('http');
|
|
5
|
-
var nano = require('nano');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* 2012 Max 'Azul' Wiehle
|
|
9
|
-
*
|
|
10
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
11
|
-
* you may not use this file except in compliance with the License.
|
|
12
|
-
* You may obtain a copy of the License at
|
|
13
|
-
*
|
|
14
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
15
|
-
*
|
|
16
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
-
* distributed under the License is distributed on an "AS-IS" BASIS,
|
|
18
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
-
* See the License for the specific language governing permissions and
|
|
20
|
-
* limitations under the License.
|
|
21
|
-
*/
|
|
22
|
-
const Database = class Couch_db extends AbstractDatabase {
|
|
23
|
-
agent;
|
|
24
|
-
db;
|
|
25
|
-
constructor(settings) {
|
|
26
|
-
super();
|
|
27
|
-
this.agent = null;
|
|
28
|
-
this.db = null;
|
|
29
|
-
this.settings = settings;
|
|
30
|
-
// force some settings
|
|
31
|
-
// used by CacheAndBufferLayer.js
|
|
32
|
-
this.settings.cache = 1000;
|
|
33
|
-
this.settings.writeInterval = 100;
|
|
34
|
-
this.settings.json = false;
|
|
35
|
-
}
|
|
36
|
-
get isAsync() { return true; }
|
|
37
|
-
async init() {
|
|
38
|
-
this.agent = new http.Agent({
|
|
39
|
-
keepAlive: true,
|
|
40
|
-
maxSockets: this.settings.maxListeners || 1,
|
|
41
|
-
});
|
|
42
|
-
const coudhDBSettings = {
|
|
43
|
-
url: `http://${this.settings.host}:${this.settings.port}`,
|
|
44
|
-
requestDefaults: {
|
|
45
|
-
agent: this.agent,
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
if (this.settings.user && this.settings.password) {
|
|
49
|
-
coudhDBSettings.requestDefaults.auth = {
|
|
50
|
-
username: this.settings.user,
|
|
51
|
-
password: this.settings.password,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
const client = nano(coudhDBSettings);
|
|
55
|
-
try {
|
|
56
|
-
await client.db.get(this.settings.database);
|
|
57
|
-
}
|
|
58
|
-
catch (err) {
|
|
59
|
-
if (err.statusCode !== 404)
|
|
60
|
-
throw err;
|
|
61
|
-
await client.db.create(this.settings.database);
|
|
62
|
-
}
|
|
63
|
-
this.db = client.use(this.settings.database);
|
|
64
|
-
}
|
|
65
|
-
async get(key) {
|
|
66
|
-
let doc;
|
|
67
|
-
try {
|
|
68
|
-
if (this.db) {
|
|
69
|
-
doc = await this.db.get(key);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
catch (err) {
|
|
73
|
-
if (err.statusCode === 404)
|
|
74
|
-
return null;
|
|
75
|
-
throw err;
|
|
76
|
-
}
|
|
77
|
-
if (doc && 'value' in doc) {
|
|
78
|
-
return doc.value;
|
|
79
|
-
}
|
|
80
|
-
return '';
|
|
81
|
-
}
|
|
82
|
-
async findKeys(key, notKey) {
|
|
83
|
-
const pfxLen = key.indexOf('*');
|
|
84
|
-
if (!this.db) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
const pfx = pfxLen < 0 ? key : key.slice(0, pfxLen);
|
|
88
|
-
const results = await this.db.find({
|
|
89
|
-
selector: {
|
|
90
|
-
_id: pfxLen < 0 ? pfx : {
|
|
91
|
-
$gte: pfx,
|
|
92
|
-
// https://docs.couchdb.org/en/3.2.2/ddocs/views/collation.html#string-ranges
|
|
93
|
-
$lte: `${pfx}\ufff0`,
|
|
94
|
-
$regex: this.createFindRegex(key, notKey).source,
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
fields: ['_id'],
|
|
98
|
-
});
|
|
99
|
-
return results.docs.map((doc) => doc._id);
|
|
100
|
-
}
|
|
101
|
-
async set(key, value) {
|
|
102
|
-
let doc;
|
|
103
|
-
if (!this.db) {
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
try {
|
|
107
|
-
doc = await this.db.get(key);
|
|
108
|
-
}
|
|
109
|
-
catch (err) {
|
|
110
|
-
if (err.statusCode !== 404)
|
|
111
|
-
throw err;
|
|
112
|
-
}
|
|
113
|
-
await this.db.insert({
|
|
114
|
-
_id: key,
|
|
115
|
-
// @ts-ignore
|
|
116
|
-
value,
|
|
117
|
-
...doc == null ? {} : {
|
|
118
|
-
_rev: doc._rev,
|
|
119
|
-
},
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
async remove(key) {
|
|
123
|
-
let header;
|
|
124
|
-
if (!this.db) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
try {
|
|
128
|
-
header = await this.db.head(key);
|
|
129
|
-
}
|
|
130
|
-
catch (err) {
|
|
131
|
-
if (err.statusCode === 404)
|
|
132
|
-
return;
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
135
|
-
// etag has additional quotation marks, remove them
|
|
136
|
-
const etag = JSON.parse(header.etag);
|
|
137
|
-
await this.db.destroy(key, etag);
|
|
138
|
-
}
|
|
139
|
-
async doBulk(bulk) {
|
|
140
|
-
if (!this.db) {
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
const keys = bulk.map((op) => op.key);
|
|
144
|
-
const revs = {};
|
|
145
|
-
// @ts-ignore
|
|
146
|
-
for (const { key, value } of (await this.db.fetchRevs({ keys })).rows) {
|
|
147
|
-
// couchDB will return error instead of value if key does not exist
|
|
148
|
-
if (value != null)
|
|
149
|
-
revs[key] = value.rev;
|
|
150
|
-
}
|
|
151
|
-
const setters = [];
|
|
152
|
-
for (const item of bulk) {
|
|
153
|
-
const set = { _id: item.key, _rev: undefined,
|
|
154
|
-
_deleted: false, value: '' };
|
|
155
|
-
if (revs[item.key] != null)
|
|
156
|
-
set._rev = revs[item.key];
|
|
157
|
-
if (item.type === 'set')
|
|
158
|
-
set.value = item.value;
|
|
159
|
-
if (item.type === 'remove')
|
|
160
|
-
set._deleted = true;
|
|
161
|
-
setters.push(set);
|
|
162
|
-
}
|
|
163
|
-
await this.db.bulk({ docs: setters });
|
|
164
|
-
}
|
|
165
|
-
async close() {
|
|
166
|
-
this.db = null;
|
|
167
|
-
if (this.agent)
|
|
168
|
-
this.agent.destroy();
|
|
169
|
-
this.agent = null;
|
|
170
|
-
}
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
exports.Database = Database;
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AbstractDatabase = require('../lib/AbstractDatabase.js');
|
|
4
|
-
var Dirty = require('dirty');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* 2011 Peter 'Pita' Martischka
|
|
8
|
-
*
|
|
9
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
10
|
-
* you may not use this file except in compliance with the License.
|
|
11
|
-
* You may obtain a copy of the License at
|
|
12
|
-
*
|
|
13
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
14
|
-
*
|
|
15
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
16
|
-
* distributed under the License is distributed on an "AS-IS" BASIS,
|
|
17
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
18
|
-
* See the License for the specific language governing permissions and
|
|
19
|
-
* limitations under the License.
|
|
20
|
-
*/
|
|
21
|
-
/*
|
|
22
|
-
*
|
|
23
|
-
* Fair warning that length may not provide the correct value upon load.
|
|
24
|
-
* See https://github.com/ether/etherpad-lite/pull/3984
|
|
25
|
-
*
|
|
26
|
-
*/
|
|
27
|
-
const Database = class extends AbstractDatabase {
|
|
28
|
-
db;
|
|
29
|
-
constructor(settings) {
|
|
30
|
-
super();
|
|
31
|
-
this.db = null;
|
|
32
|
-
if (!settings || !settings.filename) {
|
|
33
|
-
// @ts-ignore
|
|
34
|
-
settings = { filename: null };
|
|
35
|
-
}
|
|
36
|
-
this.settings = settings;
|
|
37
|
-
// set default settings
|
|
38
|
-
this.settings.cache = 0;
|
|
39
|
-
this.settings.writeInterval = 0;
|
|
40
|
-
this.settings.json = false;
|
|
41
|
-
}
|
|
42
|
-
init(callback) {
|
|
43
|
-
this.db = new Dirty(this.settings.filename);
|
|
44
|
-
this.db.on('load', (err) => {
|
|
45
|
-
callback();
|
|
46
|
-
});
|
|
47
|
-
}
|
|
48
|
-
get(key, callback) {
|
|
49
|
-
callback(null, this.db.get(key));
|
|
50
|
-
}
|
|
51
|
-
findKeys(key, notKey, callback) {
|
|
52
|
-
const keys = [];
|
|
53
|
-
const regex = this.createFindRegex(key, notKey);
|
|
54
|
-
this.db.forEach((key, val) => {
|
|
55
|
-
if (key.search(regex) !== -1) {
|
|
56
|
-
keys.push(key);
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
callback(null, keys);
|
|
60
|
-
}
|
|
61
|
-
set(key, value, callback) {
|
|
62
|
-
this.db.set(key, value, callback);
|
|
63
|
-
}
|
|
64
|
-
remove(key, callback) {
|
|
65
|
-
this.db.rm(key, callback);
|
|
66
|
-
}
|
|
67
|
-
close(callback) {
|
|
68
|
-
this.db.close();
|
|
69
|
-
this.db = null;
|
|
70
|
-
if (callback)
|
|
71
|
-
callback();
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
exports.Database = Database;
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AbstractDatabase = require('../lib/AbstractDatabase.js');
|
|
4
|
-
var Dirty = require('dirty');
|
|
5
|
-
|
|
6
|
-
const Database = class extends AbstractDatabase {
|
|
7
|
-
db;
|
|
8
|
-
constructor(settings) {
|
|
9
|
-
super();
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
this.db = null;
|
|
12
|
-
if (!settings || !settings.filename) {
|
|
13
|
-
settings = {};
|
|
14
|
-
}
|
|
15
|
-
this.settings = settings;
|
|
16
|
-
// set default settings
|
|
17
|
-
this.settings.cache = 0;
|
|
18
|
-
this.settings.writeInterval = 0;
|
|
19
|
-
this.settings.json = false;
|
|
20
|
-
}
|
|
21
|
-
init(callback) {
|
|
22
|
-
this.db = new Dirty.Dirty(this.settings.filename);
|
|
23
|
-
this.db.on('load', (err) => {
|
|
24
|
-
callback();
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
get(key, callback) {
|
|
28
|
-
callback(null, this.db.get(key));
|
|
29
|
-
}
|
|
30
|
-
findKeys(key, notKey, callback) {
|
|
31
|
-
const keys = [];
|
|
32
|
-
const regex = this.createFindRegex(key, notKey);
|
|
33
|
-
this.db.forEach((key, val) => {
|
|
34
|
-
if (key.search(regex) !== -1) {
|
|
35
|
-
keys.push(key);
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
callback(null, keys);
|
|
39
|
-
}
|
|
40
|
-
set(key, value, callback) {
|
|
41
|
-
this.db.set(key, value, callback);
|
|
42
|
-
const databasePath = require('path').dirname(this.settings.filename);
|
|
43
|
-
require('simple-git')(databasePath)
|
|
44
|
-
.silent(true)
|
|
45
|
-
.add('./*.db')
|
|
46
|
-
.commit('Automated commit...')
|
|
47
|
-
.push(['-u', 'origin', 'master'], () => console.debug('Stored git commit'));
|
|
48
|
-
}
|
|
49
|
-
remove(key, callback) {
|
|
50
|
-
this.db.rm(key, callback);
|
|
51
|
-
}
|
|
52
|
-
close(callback) {
|
|
53
|
-
this.db.close();
|
|
54
|
-
if (callback)
|
|
55
|
-
callback();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
exports.Database = Database;
|
|
@@ -1,243 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AbstractDatabase = require('../lib/AbstractDatabase.js');
|
|
4
|
-
var assert = require('assert');
|
|
5
|
-
var buffer = require('buffer');
|
|
6
|
-
var crypto = require('crypto');
|
|
7
|
-
var elasticsearch8 = require('elasticsearch8');
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* 2015 Visionist, Inc.
|
|
11
|
-
*
|
|
12
|
-
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
13
|
-
* you may not use this file except in compliance with the License.
|
|
14
|
-
* You may obtain a copy of the License at
|
|
15
|
-
*
|
|
16
|
-
* http://www.apache.org/licenses/LICENSE-2.0
|
|
17
|
-
*
|
|
18
|
-
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
-
* distributed under the License is distributed on an "AS-IS" BASIS,
|
|
20
|
-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
-
* See the License for the specific language governing permissions and
|
|
22
|
-
* limitations under the License.
|
|
23
|
-
*/
|
|
24
|
-
const schema = '2';
|
|
25
|
-
const keyToId = (key) => {
|
|
26
|
-
const keyBuf = buffer.Buffer.from(key);
|
|
27
|
-
return keyBuf.length > 512 ? crypto.createHash('sha512').update(keyBuf).digest('hex') : key;
|
|
28
|
-
};
|
|
29
|
-
const mappings = {
|
|
30
|
-
// _id is expected to equal key, unless the UTF-8 encoded key is > 512 bytes, in which case it is
|
|
31
|
-
// the hex-encoded sha512 hash of the UTF-8 encoded key.
|
|
32
|
-
properties: {
|
|
33
|
-
key: { type: 'wildcard' },
|
|
34
|
-
value: { type: 'object', enabled: false }, // Values should be opaque to Elasticsearch.
|
|
35
|
-
},
|
|
36
|
-
};
|
|
37
|
-
const migrateToSchema2 = async (client, v1BaseIndex, v2Index, logger) => {
|
|
38
|
-
let recordsMigratedLastLogged = 0;
|
|
39
|
-
let recordsMigrated = 0;
|
|
40
|
-
const totals = new Map();
|
|
41
|
-
logger.info('Attempting elasticsearch record migration from schema v1 at base index ' +
|
|
42
|
-
`${v1BaseIndex} to schema v2 at index ${v2Index}...`);
|
|
43
|
-
const indices = await client.indices.get({ index: [v1BaseIndex, `${v1BaseIndex}-*-*`] });
|
|
44
|
-
const scrollIds = new Map();
|
|
45
|
-
const q = [];
|
|
46
|
-
try {
|
|
47
|
-
for (const index of Object.keys(indices)) {
|
|
48
|
-
const res = await client.search({ index, scroll: '10m' });
|
|
49
|
-
scrollIds.set(index, res._scroll_id);
|
|
50
|
-
q.push({ index, res });
|
|
51
|
-
}
|
|
52
|
-
while (q.length) {
|
|
53
|
-
const { index, res: { hits: { hits, total: { value: total } } } } = q.shift();
|
|
54
|
-
if (hits.length === 0)
|
|
55
|
-
continue;
|
|
56
|
-
totals.set(index, total);
|
|
57
|
-
const body = [];
|
|
58
|
-
for (const { _id, _type, _source: { val } } of hits) {
|
|
59
|
-
let key = `${_type}:${_id}`;
|
|
60
|
-
if (v1BaseIndex && index !== v1BaseIndex) {
|
|
61
|
-
const parts = index.slice(v1BaseIndex.length + 1).split('-');
|
|
62
|
-
if (parts.length !== 2) {
|
|
63
|
-
throw new Error(`unable to migrate records from index ${index} due to data ambiguity`);
|
|
64
|
-
}
|
|
65
|
-
key = `${parts[0]}:${decodeURIComponent(_type)}:${parts[1]}:${_id}`;
|
|
66
|
-
}
|
|
67
|
-
body.push({ index: { _id: keyToId(key) } }, { key, value: JSON.parse(val) });
|
|
68
|
-
}
|
|
69
|
-
await client.bulk({ index: v2Index, body });
|
|
70
|
-
recordsMigrated += hits.length;
|
|
71
|
-
if (Math.floor(recordsMigrated / 100) > Math.floor(recordsMigratedLastLogged / 100)) {
|
|
72
|
-
const total = [...totals.values()].reduce((a, b) => a + b, 0);
|
|
73
|
-
logger.info(`Migrated ${recordsMigrated} records out of ${total}`);
|
|
74
|
-
recordsMigratedLastLogged = recordsMigrated;
|
|
75
|
-
}
|
|
76
|
-
q.push({ index, res: (await client.scroll({ scroll: '5m', scroll_id: scrollIds.get(index) })) });
|
|
77
|
-
}
|
|
78
|
-
logger.info(`Finished migrating ${recordsMigrated} records`);
|
|
79
|
-
}
|
|
80
|
-
finally {
|
|
81
|
-
await Promise.all([...scrollIds.values()].map((scrollId) => client.clearScroll({ scroll_id: scrollId })));
|
|
82
|
-
}
|
|
83
|
-
};
|
|
84
|
-
const Database = class extends AbstractDatabase {
|
|
85
|
-
_client;
|
|
86
|
-
_index;
|
|
87
|
-
_indexClean;
|
|
88
|
-
_q;
|
|
89
|
-
constructor(settings) {
|
|
90
|
-
super();
|
|
91
|
-
this._client = null;
|
|
92
|
-
this.settings = {
|
|
93
|
-
host: '127.0.0.1',
|
|
94
|
-
port: '9200',
|
|
95
|
-
base_index: 'ueberes',
|
|
96
|
-
migrate_to_newer_schema: false,
|
|
97
|
-
// for a list of valid API values see:
|
|
98
|
-
// https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/configuration.html#config-options
|
|
99
|
-
api: '7.6',
|
|
100
|
-
...settings || {},
|
|
101
|
-
json: false, // Elasticsearch will do the JSON conversion as necessary.
|
|
102
|
-
};
|
|
103
|
-
this._index = `${this.settings.base_index}_s${schema}`;
|
|
104
|
-
this._q = { index: this._index };
|
|
105
|
-
this._indexClean = true;
|
|
106
|
-
}
|
|
107
|
-
get isAsync() { return true; }
|
|
108
|
-
async _refreshIndex() {
|
|
109
|
-
if (this._indexClean)
|
|
110
|
-
return;
|
|
111
|
-
this._indexClean = true;
|
|
112
|
-
await this._client.indices.refresh(this._q);
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Initialize the elasticsearch client, then ping the server to ensure that a
|
|
116
|
-
* connection was made.
|
|
117
|
-
*/
|
|
118
|
-
async init() {
|
|
119
|
-
// create elasticsearch client
|
|
120
|
-
const client = new elasticsearch8.Client({
|
|
121
|
-
node: `http://${this.settings.host}:${this.settings.port}`,
|
|
122
|
-
});
|
|
123
|
-
await client.ping();
|
|
124
|
-
if (!(await client.indices.exists({ index: this._index }))) {
|
|
125
|
-
let tmpIndex;
|
|
126
|
-
const exists = await client.indices.exists({ index: this.settings.base_index });
|
|
127
|
-
if (exists && !this.settings.migrate_to_newer_schema) {
|
|
128
|
-
throw new Error(`Data exists under the legacy index (schema) named ${this.settings.base_index}. ` +
|
|
129
|
-
'Set migrate_to_newer_schema to true to copy the existing data to a new index ' +
|
|
130
|
-
`named ${this._index}.`);
|
|
131
|
-
}
|
|
132
|
-
let attempt = 0;
|
|
133
|
-
while (true) {
|
|
134
|
-
tmpIndex = `${this._index}_${exists ? 'migrate_attempt_' : 'i'}${attempt++}`;
|
|
135
|
-
if (!(await client.indices.exists({ index: tmpIndex })))
|
|
136
|
-
break;
|
|
137
|
-
}
|
|
138
|
-
await client.indices.create({ index: tmpIndex, mappings: mappings });
|
|
139
|
-
if (exists)
|
|
140
|
-
await migrateToSchema2(client, this.settings.base_index, tmpIndex, this.logger);
|
|
141
|
-
await client.indices.putAlias({ index: tmpIndex, name: this._index });
|
|
142
|
-
}
|
|
143
|
-
const indices = Object.values((await client.indices.get({ index: this._index })));
|
|
144
|
-
assert.equal(indices.length, 1);
|
|
145
|
-
try {
|
|
146
|
-
assert.deepEqual(indices[0].mappings, mappings);
|
|
147
|
-
}
|
|
148
|
-
catch (err) {
|
|
149
|
-
this.logger.warn(`Index ${this._index} mappings does not match expected; ` +
|
|
150
|
-
`attempting to use index anyway. Details: ${err}`);
|
|
151
|
-
}
|
|
152
|
-
this._client = client;
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* This function provides read functionality to the database.
|
|
156
|
-
*
|
|
157
|
-
* @param {String} key Key
|
|
158
|
-
*/
|
|
159
|
-
async get(key) {
|
|
160
|
-
const res = await this._client.get({ ...this._q, id: keyToId(key) }, { ignore: [404] });
|
|
161
|
-
if (!res.found)
|
|
162
|
-
return null;
|
|
163
|
-
return res._source.value;
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* @param key Search key, which uses an asterisk (*) as the wild card.
|
|
167
|
-
* @param notKey Used to filter the result set
|
|
168
|
-
*/
|
|
169
|
-
async findKeys(key, notKey) {
|
|
170
|
-
await this._refreshIndex();
|
|
171
|
-
const q = {
|
|
172
|
-
...this._q,
|
|
173
|
-
body: {
|
|
174
|
-
query: {
|
|
175
|
-
bool: {
|
|
176
|
-
filter: { wildcard: { key: { value: key } } },
|
|
177
|
-
...notKey == null ? {} : {
|
|
178
|
-
must_not: { wildcard: { key: { value: notKey } } },
|
|
179
|
-
},
|
|
180
|
-
},
|
|
181
|
-
},
|
|
182
|
-
},
|
|
183
|
-
};
|
|
184
|
-
const { hits: hits } = await this._client.search(q);
|
|
185
|
-
return hits.hits.map((h) => h._source.key);
|
|
186
|
-
}
|
|
187
|
-
/**
|
|
188
|
-
* This function provides write functionality to the database.
|
|
189
|
-
*
|
|
190
|
-
* @param {String} key Record identifier.
|
|
191
|
-
* @param {JSON|String} value The value to store in the database.
|
|
192
|
-
*/
|
|
193
|
-
async set(key, value) {
|
|
194
|
-
this._indexClean = false;
|
|
195
|
-
await this._client.index({ ...this._q, id: keyToId(key), body: { key, value } });
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* This function provides delete functionality to the database.
|
|
199
|
-
*
|
|
200
|
-
* The index, type, and ID will be parsed from the key, and this document will
|
|
201
|
-
* be deleted from the database.
|
|
202
|
-
*
|
|
203
|
-
* @param {String} key Record identifier.
|
|
204
|
-
*/
|
|
205
|
-
async remove(key) {
|
|
206
|
-
this._indexClean = false;
|
|
207
|
-
await this._client.delete({ ...this._q, id: keyToId(key) }, { ignore: [404] });
|
|
208
|
-
}
|
|
209
|
-
/**
|
|
210
|
-
* This uses the bulk upload functionality of elasticsearch (url:port/_bulk).
|
|
211
|
-
*
|
|
212
|
-
* The CacheAndBufferLayer will periodically (every this.settings.writeInterval)
|
|
213
|
-
* flush writes that have already been done in the local cache out to the database.
|
|
214
|
-
*
|
|
215
|
-
* @param {Array} bulk An array of JSON data in the format:
|
|
216
|
-
* {"type":type, "key":key, "value":value}
|
|
217
|
-
*/
|
|
218
|
-
async doBulk(bulk) {
|
|
219
|
-
// bulk is an array of JSON:
|
|
220
|
-
// example: [{"type":"set", "key":"sessionstorage:{id}", "value":{"cookie":{...}}]
|
|
221
|
-
const operations = [];
|
|
222
|
-
for (const { type, key, value } of bulk) {
|
|
223
|
-
this._indexClean = false;
|
|
224
|
-
switch (type) {
|
|
225
|
-
case 'set':
|
|
226
|
-
operations.push({ index: { _id: keyToId(key) } });
|
|
227
|
-
operations.push({ key, value });
|
|
228
|
-
break;
|
|
229
|
-
case 'remove':
|
|
230
|
-
operations.push({ delete: { _id: keyToId(key) } });
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
await this._client.bulk({ ...this._q, body: operations });
|
|
235
|
-
}
|
|
236
|
-
async close() {
|
|
237
|
-
if (this._client != null)
|
|
238
|
-
this._client.close();
|
|
239
|
-
this._client = null;
|
|
240
|
-
}
|
|
241
|
-
};
|
|
242
|
-
|
|
243
|
-
exports.Database = Database;
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var AbstractDatabase = require('../lib/AbstractDatabase.js');
|
|
4
|
-
|
|
5
|
-
const Database = class MemoryDB extends AbstractDatabase {
|
|
6
|
-
_data;
|
|
7
|
-
constructor(settings) {
|
|
8
|
-
super();
|
|
9
|
-
this.settings = settings;
|
|
10
|
-
settings.json = false;
|
|
11
|
-
settings.cache = 0;
|
|
12
|
-
settings.writeInterval = 0;
|
|
13
|
-
this._data = null;
|
|
14
|
-
}
|
|
15
|
-
get isAsync() { return true; }
|
|
16
|
-
close() {
|
|
17
|
-
this._data = null;
|
|
18
|
-
}
|
|
19
|
-
findKeys(key, notKey) {
|
|
20
|
-
const regex = this.createFindRegex(key, notKey);
|
|
21
|
-
return [...this._data.keys()].filter((k) => regex.test(k));
|
|
22
|
-
}
|
|
23
|
-
get(key) {
|
|
24
|
-
return this._data.get(key);
|
|
25
|
-
}
|
|
26
|
-
init() {
|
|
27
|
-
this._data = this.settings.data || new Map();
|
|
28
|
-
}
|
|
29
|
-
remove(key) {
|
|
30
|
-
this._data.delete(key);
|
|
31
|
-
}
|
|
32
|
-
set(key, value) {
|
|
33
|
-
this._data.set(key, value);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
exports.Database = Database;
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var events = require('events');
|
|
4
|
-
|
|
5
|
-
const Database = class extends events.EventEmitter {
|
|
6
|
-
settings;
|
|
7
|
-
mock;
|
|
8
|
-
constructor(settings) {
|
|
9
|
-
super();
|
|
10
|
-
this.settings = {
|
|
11
|
-
writeInterval: 1,
|
|
12
|
-
...settings,
|
|
13
|
-
};
|
|
14
|
-
settings.mock = this;
|
|
15
|
-
this.settings = settings;
|
|
16
|
-
console.log("Initialized");
|
|
17
|
-
}
|
|
18
|
-
close(cb) {
|
|
19
|
-
this.emit('close', cb);
|
|
20
|
-
}
|
|
21
|
-
doBulk(ops, cb) {
|
|
22
|
-
this.emit('doBulk', ops, cb);
|
|
23
|
-
}
|
|
24
|
-
findKeys(key, notKey, cb) {
|
|
25
|
-
this.emit('findKeys', key, notKey, cb);
|
|
26
|
-
}
|
|
27
|
-
get(key, cb) {
|
|
28
|
-
this.emit('get', key, cb);
|
|
29
|
-
}
|
|
30
|
-
async init(cb) {
|
|
31
|
-
this.emit('init', cb());
|
|
32
|
-
}
|
|
33
|
-
remove(key, cb) {
|
|
34
|
-
this.emit('remove', key, cb);
|
|
35
|
-
}
|
|
36
|
-
set(key, value, cb) {
|
|
37
|
-
this.emit('set', key, value, cb);
|
|
38
|
-
}
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
exports.Database = Database;
|