ueberdb2 4.0.11 → 4.0.15
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/.eslintignore +2 -0
- package/.eslintrc.cjs +44 -5
- package/databases/{cassandra_db.js → cassandra_db.ts} +45 -30
- package/databases/{couch_db.js → couch_db.ts} +78 -31
- package/databases/{dirty_db.js → dirty_db.ts} +19 -14
- package/databases/{dirty_git_db.js → dirty_git_db.ts} +19 -15
- package/databases/{elasticsearch_db.js → elasticsearch_db.ts} +30 -21
- package/databases/{memory_db.js → memory_db.ts} +8 -8
- package/databases/mock_db.ts +43 -0
- package/databases/{mongodb_db.js → mongodb_db.ts} +22 -16
- package/databases/{mssql_db.js → mssql_db.ts} +29 -21
- package/databases/{mysql_db.js → mysql_db.ts} +20 -15
- package/databases/{postgres_db.js → postgres_db.ts} +37 -22
- package/databases/{postgrespool_db.js → postgrespool_db.ts} +3 -3
- package/databases/redis_db.ts +129 -0
- package/databases/{rethink_db.js → rethink_db.ts} +35 -19
- package/databases/{sqlite_db.js → sqlite_db.ts} +37 -36
- package/docker-compose.yml +44 -0
- package/{index.js → index.ts} +76 -25
- package/lib/AbstractDatabase.ts +79 -0
- package/lib/{CacheAndBufferLayer.js → CacheAndBufferLayer.ts} +17 -16
- package/lib/{logging.js → logging.ts} +10 -6
- package/package.json +17 -3
- package/test/lib/{databases.js → databases.ts} +8 -5
- package/test/test.ts +328 -0
- package/test/test_bulk.ts +69 -0
- package/test/{test_elasticsearch.js → test_elasticsearch.ts} +48 -53
- package/test/{test_findKeys.js → test_findKeys.ts} +15 -17
- package/test/{test_flush.js → test_flush.ts} +16 -22
- package/test/test_getSub.ts +28 -0
- package/test/test_lru.ts +151 -0
- package/test/test_memory.ts +32 -0
- package/test/{test_metrics.js → test_metrics.ts} +73 -68
- package/test/{test_mysql.js → test_mysql.ts} +16 -22
- package/test/test_postgres.ts +16 -0
- package/test/{test_setSub.js → test_setSub.ts} +8 -12
- package/test/test_tojson.ts +34 -0
- package/databases/mock_db.js +0 -42
- package/databases/redis_db.js +0 -96
- package/lib/AbstractDatabase.js +0 -37
- package/test/test.js +0 -328
- package/test/test_bulk.js +0 -69
- package/test/test_getSub.js +0 -31
- package/test/test_lru.js +0 -145
- package/test/test_memory.js +0 -31
- package/test/test_postgres.js +0 -16
- package/test/test_tojson.js +0 -37
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
1
|
/**
|
|
3
2
|
* 2015 Visionist, Inc.
|
|
4
3
|
*
|
|
@@ -15,17 +14,19 @@
|
|
|
15
14
|
* limitations under the License.
|
|
16
15
|
*/
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
|
|
18
|
+
import {equal, strict} from 'assert';
|
|
19
|
+
|
|
20
|
+
import {Buffer} from 'buffer';
|
|
21
|
+
import {createHash} from 'crypto';
|
|
22
|
+
import {Client} from 'elasticsearch7';
|
|
23
|
+
import {BulkObject} from './cassandra_db';
|
|
23
24
|
|
|
24
25
|
const schema = '2';
|
|
25
26
|
|
|
26
|
-
const keyToId = (key) => {
|
|
27
|
+
const keyToId = (key:string) => {
|
|
27
28
|
const keyBuf = Buffer.from(key);
|
|
28
|
-
return keyBuf.length > 512 ?
|
|
29
|
+
return keyBuf.length > 512 ? createHash('sha512').update(keyBuf).digest('hex') : key;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
const mappings = {
|
|
@@ -37,7 +38,7 @@ const mappings = {
|
|
|
37
38
|
},
|
|
38
39
|
};
|
|
39
40
|
|
|
40
|
-
const migrateToSchema2 = async (client, v1BaseIndex, v2Index, logger) => {
|
|
41
|
+
const migrateToSchema2 = async (client: any, v1BaseIndex: string | undefined, v2Index: string, logger: any) => {
|
|
41
42
|
let recordsMigratedLastLogged = 0;
|
|
42
43
|
let recordsMigrated = 0;
|
|
43
44
|
const totals = new Map();
|
|
@@ -53,13 +54,13 @@ const migrateToSchema2 = async (client, v1BaseIndex, v2Index, logger) => {
|
|
|
53
54
|
q.push({index, res});
|
|
54
55
|
}
|
|
55
56
|
while (q.length) {
|
|
56
|
-
const {index, res: {hits: {hits, total: {value: total}}}} = q.shift();
|
|
57
|
+
const {index, res: {hits: {hits, total: {value: total}}}}:any = q.shift();
|
|
57
58
|
if (hits.length === 0) continue;
|
|
58
59
|
totals.set(index, total);
|
|
59
60
|
const body = [];
|
|
60
61
|
for (const {_id, _type, _source: {val}} of hits) {
|
|
61
62
|
let key = `${_type}:${_id}`;
|
|
62
|
-
if (index !== v1BaseIndex) {
|
|
63
|
+
if (v1BaseIndex && index !== v1BaseIndex) {
|
|
63
64
|
const parts = index.slice(v1BaseIndex.length + 1).split('-');
|
|
64
65
|
if (parts.length !== 2) {
|
|
65
66
|
throw new Error(`unable to migrate records from index ${index} due to data ambiguity`);
|
|
@@ -71,6 +72,7 @@ const migrateToSchema2 = async (client, v1BaseIndex, v2Index, logger) => {
|
|
|
71
72
|
await client.bulk({index: v2Index, body});
|
|
72
73
|
recordsMigrated += hits.length;
|
|
73
74
|
if (Math.floor(recordsMigrated / 100) > Math.floor(recordsMigratedLastLogged / 100)) {
|
|
75
|
+
// @ts-ignore
|
|
74
76
|
const total = [...totals.values()].reduce((a, b) => a + b, 0);
|
|
75
77
|
logger.info(`Migrated ${recordsMigrated} records out of ${total}`);
|
|
76
78
|
recordsMigratedLastLogged = recordsMigrated;
|
|
@@ -80,12 +82,17 @@ const migrateToSchema2 = async (client, v1BaseIndex, v2Index, logger) => {
|
|
|
80
82
|
}
|
|
81
83
|
logger.info(`Finished migrating ${recordsMigrated} records`);
|
|
82
84
|
} finally {
|
|
85
|
+
// @ts-ignore
|
|
83
86
|
await Promise.all([...scrollIds.values()].map((scrollId) => client.clearScroll({scrollId})));
|
|
84
87
|
}
|
|
85
88
|
};
|
|
86
89
|
|
|
87
|
-
|
|
88
|
-
|
|
90
|
+
export const Database = class extends AbstractDatabase {
|
|
91
|
+
private _client: any;
|
|
92
|
+
private readonly _index: any;
|
|
93
|
+
private _indexClean: boolean;
|
|
94
|
+
private readonly _q: {index: any};
|
|
95
|
+
constructor(settings:Settings) {
|
|
89
96
|
super();
|
|
90
97
|
this._client = null;
|
|
91
98
|
this.settings = {
|
|
@@ -118,12 +125,13 @@ exports.Database = class extends AbstractDatabase {
|
|
|
118
125
|
*/
|
|
119
126
|
async init() {
|
|
120
127
|
// create elasticsearch client
|
|
121
|
-
const client = new
|
|
128
|
+
const client = new Client({
|
|
122
129
|
node: `http://${this.settings.host}:${this.settings.port}`,
|
|
123
130
|
});
|
|
124
131
|
await client.ping();
|
|
125
132
|
if (!(await client.indices.exists({index: this._index})).body) {
|
|
126
133
|
let tmpIndex;
|
|
134
|
+
// @ts-ignore
|
|
127
135
|
const {body: migrate} = await client.indices.exists({index: this.settings.base_index});
|
|
128
136
|
if (migrate && !this.settings.migrate_to_newer_schema) {
|
|
129
137
|
throw new Error(
|
|
@@ -141,8 +149,9 @@ exports.Database = class extends AbstractDatabase {
|
|
|
141
149
|
await client.indices.putAlias({index: tmpIndex, name: this._index});
|
|
142
150
|
}
|
|
143
151
|
const indices = Object.values((await client.indices.get({index: this._index})).body);
|
|
144
|
-
|
|
152
|
+
equal(indices.length, 1);
|
|
145
153
|
try {
|
|
154
|
+
// @ts-ignore
|
|
146
155
|
assert.deepEqual(indices[0].mappings, mappings);
|
|
147
156
|
} catch (err) {
|
|
148
157
|
this.logger.warn(`Index ${this._index} mappings does not match expected; ` +
|
|
@@ -156,7 +165,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
156
165
|
*
|
|
157
166
|
* @param {String} key Key
|
|
158
167
|
*/
|
|
159
|
-
async get(key) {
|
|
168
|
+
async get(key:string) {
|
|
160
169
|
const {body} = await this._client.get({...this._q, id: keyToId(key)}, {ignore: [404]});
|
|
161
170
|
if (!body.found) return null;
|
|
162
171
|
return body._source.value;
|
|
@@ -166,7 +175,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
166
175
|
* @param key Search key, which uses an asterisk (*) as the wild card.
|
|
167
176
|
* @param notKey Used to filter the result set
|
|
168
177
|
*/
|
|
169
|
-
async findKeys(key, notKey) {
|
|
178
|
+
async findKeys(key:string, notKey:string) {
|
|
170
179
|
await this._refreshIndex();
|
|
171
180
|
const q = {
|
|
172
181
|
...this._q,
|
|
@@ -182,7 +191,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
182
191
|
},
|
|
183
192
|
};
|
|
184
193
|
const {body: {hits: {hits}}} = await this._client.search(q);
|
|
185
|
-
return hits.map((h) => h._source.key);
|
|
194
|
+
return hits.map((h:{_source:{key:string}}) => h._source.key);
|
|
186
195
|
}
|
|
187
196
|
|
|
188
197
|
/**
|
|
@@ -191,7 +200,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
191
200
|
* @param {String} key Record identifier.
|
|
192
201
|
* @param {JSON|String} value The value to store in the database.
|
|
193
202
|
*/
|
|
194
|
-
async set(key, value) {
|
|
203
|
+
async set(key: string, value:string) {
|
|
195
204
|
this._indexClean = false;
|
|
196
205
|
await this._client.index({...this._q, id: keyToId(key), body: {key, value}});
|
|
197
206
|
}
|
|
@@ -204,7 +213,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
204
213
|
*
|
|
205
214
|
* @param {String} key Record identifier.
|
|
206
215
|
*/
|
|
207
|
-
async remove(key) {
|
|
216
|
+
async remove(key:string) {
|
|
208
217
|
this._indexClean = false;
|
|
209
218
|
await this._client.delete({...this._q, id: keyToId(key)}, {ignore: [404]});
|
|
210
219
|
}
|
|
@@ -218,7 +227,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
218
227
|
* @param {Array} bulk An array of JSON data in the format:
|
|
219
228
|
* {"type":type, "key":key, "value":value}
|
|
220
229
|
*/
|
|
221
|
-
async doBulk(bulk) {
|
|
230
|
+
async doBulk(bulk: BulkObject[]) {
|
|
222
231
|
// bulk is an array of JSON:
|
|
223
232
|
// example: [{"type":"set", "key":"sessionstorage:{id}", "value":{"cookie":{...}}]
|
|
224
233
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
|
|
2
2
|
|
|
3
|
-
const AbstractDatabase = require('../lib/AbstractDatabase');
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
export const Database = class MemoryDB extends AbstractDatabase {
|
|
5
|
+
private _data: any;
|
|
6
|
+
constructor(settings:Settings) {
|
|
7
7
|
super();
|
|
8
8
|
this.settings = settings;
|
|
9
9
|
settings.json = false;
|
|
@@ -18,12 +18,12 @@ exports.Database = class extends AbstractDatabase {
|
|
|
18
18
|
this._data = null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
findKeys(key, notKey) {
|
|
21
|
+
findKeys(key:string, notKey:string) {
|
|
22
22
|
const regex = this.createFindRegex(key, notKey);
|
|
23
23
|
return [...this._data.keys()].filter((k) => regex.test(k));
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
get(key) {
|
|
26
|
+
get(key:string) {
|
|
27
27
|
return this._data.get(key);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -31,11 +31,11 @@ exports.Database = class extends AbstractDatabase {
|
|
|
31
31
|
this._data = this.settings.data || new Map();
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
remove(key) {
|
|
34
|
+
remove(key:string) {
|
|
35
35
|
this._data.delete(key);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
set(key, value) {
|
|
38
|
+
set(key:string, value:string) {
|
|
39
39
|
this._data.set(key, value);
|
|
40
40
|
}
|
|
41
41
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import {Settings} from '../lib/AbstractDatabase';
|
|
2
|
+
|
|
3
|
+
import events from 'events';
|
|
4
|
+
|
|
5
|
+
export const Database = class extends events.EventEmitter {
|
|
6
|
+
private settings: Settings;
|
|
7
|
+
constructor(settings:Settings) {
|
|
8
|
+
super();
|
|
9
|
+
this.settings = {
|
|
10
|
+
writeInterval: 1,
|
|
11
|
+
...settings,
|
|
12
|
+
};
|
|
13
|
+
settings.mock = this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
close(cb: ()=>{}) {
|
|
17
|
+
this.emit('close', cb);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
doBulk(ops:string, cb: ()=>{}) {
|
|
21
|
+
this.emit('doBulk', ops, cb);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
findKeys(key:string, notKey:string, cb:()=>{}) {
|
|
25
|
+
this.emit('findKeys', key, notKey, cb);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get(key:string, cb:()=>{}) {
|
|
29
|
+
this.emit('get', key, cb);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
init(cb:()=>{}) {
|
|
33
|
+
this.emit('init', cb);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
remove(key:string, cb:()=>{}) {
|
|
37
|
+
this.emit('remove', key, cb);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
set(key:string, value:string, cb:()=>{}) {
|
|
41
|
+
this.emit('set', key, value, cb);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
1
|
/**
|
|
3
2
|
* 2020 Sylchauf
|
|
4
3
|
*
|
|
@@ -15,10 +14,16 @@
|
|
|
15
14
|
* limitations under the License.
|
|
16
15
|
*/
|
|
17
16
|
|
|
18
|
-
|
|
17
|
+
import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
|
|
18
|
+
import {Func} from 'mocha';
|
|
19
|
+
import {BulkObject} from './cassandra_db';
|
|
19
20
|
|
|
20
21
|
exports.Database = class extends AbstractDatabase {
|
|
21
|
-
|
|
22
|
+
private interval: any;
|
|
23
|
+
private database: any;
|
|
24
|
+
private client: any;
|
|
25
|
+
private collection: any;
|
|
26
|
+
constructor(settings:Settings) {
|
|
22
27
|
super();
|
|
23
28
|
this.settings = settings;
|
|
24
29
|
|
|
@@ -44,10 +49,10 @@ exports.Database = class extends AbstractDatabase {
|
|
|
44
49
|
}, 10000);
|
|
45
50
|
}
|
|
46
51
|
|
|
47
|
-
init(callback) {
|
|
52
|
+
init(callback:Function) {
|
|
48
53
|
const MongoClient = require('mongodb').MongoClient;
|
|
49
54
|
|
|
50
|
-
MongoClient.connect(this.settings.url, (err, client) => {
|
|
55
|
+
MongoClient.connect(this.settings.url, (err:any, client:any) => {
|
|
51
56
|
if (!err) {
|
|
52
57
|
this.client = client;
|
|
53
58
|
this.database = client.db(this.settings.database);
|
|
@@ -60,8 +65,8 @@ exports.Database = class extends AbstractDatabase {
|
|
|
60
65
|
this.schedulePing();
|
|
61
66
|
}
|
|
62
67
|
|
|
63
|
-
get(key, callback) {
|
|
64
|
-
this.collection.findOne({_id: key}, (err, document) => {
|
|
68
|
+
get(key:string, callback:Function) {
|
|
69
|
+
this.collection.findOne({_id: key}, (err:any, document:any) => {
|
|
65
70
|
if (err) callback(err);
|
|
66
71
|
else callback(null, document ? document.value : null);
|
|
67
72
|
});
|
|
@@ -69,7 +74,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
69
74
|
this.schedulePing();
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
findKeys(key, notKey, callback) {
|
|
77
|
+
findKeys(key:string, notKey:string, callback:Function) {
|
|
73
78
|
const selector = {
|
|
74
79
|
$and: [
|
|
75
80
|
{_id: {$regex: `${key.replace(/\*/g, '')}`}},
|
|
@@ -77,23 +82,24 @@ exports.Database = class extends AbstractDatabase {
|
|
|
77
82
|
};
|
|
78
83
|
|
|
79
84
|
if (notKey) {
|
|
85
|
+
// @ts-ignore
|
|
80
86
|
selector.$and.push({_id: {$not: {$regex: `${notKey.replace(/\*/g, '')}`}}});
|
|
81
87
|
}
|
|
82
88
|
|
|
83
|
-
this.collection.find(selector, async (err, res) => {
|
|
89
|
+
this.collection.find(selector, async (err:any, res:any) => {
|
|
84
90
|
if (err) {
|
|
85
91
|
callback(err);
|
|
86
92
|
} else {
|
|
87
93
|
const data = await res.toArray();
|
|
88
94
|
|
|
89
|
-
callback(null, data.map((i) => i._id));
|
|
95
|
+
callback(null, data.map((i:any) => i._id));
|
|
90
96
|
}
|
|
91
97
|
});
|
|
92
98
|
|
|
93
99
|
this.schedulePing();
|
|
94
100
|
}
|
|
95
101
|
|
|
96
|
-
set(key, value, callback) {
|
|
102
|
+
set(key:string, value:string, callback:Function) {
|
|
97
103
|
if (key.length > 100) {
|
|
98
104
|
callback('Your Key can only be 100 chars');
|
|
99
105
|
} else {
|
|
@@ -103,13 +109,13 @@ exports.Database = class extends AbstractDatabase {
|
|
|
103
109
|
this.schedulePing();
|
|
104
110
|
}
|
|
105
111
|
|
|
106
|
-
remove(key, callback) {
|
|
112
|
+
remove(key:string, callback:Function) {
|
|
107
113
|
this.collection.remove({_id: key}, callback);
|
|
108
114
|
|
|
109
115
|
this.schedulePing();
|
|
110
116
|
}
|
|
111
117
|
|
|
112
|
-
doBulk(bulk, callback) {
|
|
118
|
+
doBulk(bulk:BulkObject[], callback:Function) {
|
|
113
119
|
const bulkMongo = this.collection.initializeOrderedBulkOp();
|
|
114
120
|
|
|
115
121
|
for (const i in bulk) {
|
|
@@ -120,16 +126,16 @@ exports.Database = class extends AbstractDatabase {
|
|
|
120
126
|
}
|
|
121
127
|
}
|
|
122
128
|
|
|
123
|
-
bulkMongo.execute().then((res) => {
|
|
129
|
+
bulkMongo.execute().then((res:any) => {
|
|
124
130
|
callback(null, res);
|
|
125
|
-
}).catch((error) => {
|
|
131
|
+
}).catch((error:any) => {
|
|
126
132
|
callback(error);
|
|
127
133
|
});
|
|
128
134
|
|
|
129
135
|
this.schedulePing();
|
|
130
136
|
}
|
|
131
137
|
|
|
132
|
-
close(callback) {
|
|
138
|
+
close(callback:any) {
|
|
133
139
|
this.clearPing();
|
|
134
140
|
this.client.close(callback);
|
|
135
141
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
1
|
/* eslint new-cap: ["error", {"capIsNewExceptions": ["mssql.NVarChar"]}] */
|
|
3
2
|
|
|
4
3
|
/**
|
|
@@ -21,12 +20,19 @@
|
|
|
21
20
|
*
|
|
22
21
|
*/
|
|
23
22
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
|
|
24
|
+
import async from 'async';
|
|
25
|
+
import mssql, {ConnectionPool} from 'mssql';
|
|
26
|
+
import {BulkObject} from './cassandra_db';
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
type RowResult = {
|
|
29
|
+
key: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
export const Database = class MSSQL extends AbstractDatabase {
|
|
34
|
+
private db: ConnectionPool | undefined;
|
|
35
|
+
constructor(settings:Settings) {
|
|
30
36
|
super();
|
|
31
37
|
settings = settings || {};
|
|
32
38
|
|
|
@@ -49,7 +55,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
49
55
|
this.settings.writeInterval = 0;
|
|
50
56
|
}
|
|
51
57
|
|
|
52
|
-
init(callback) {
|
|
58
|
+
init(callback:(err: any)=>{}) {
|
|
53
59
|
const sqlCreate =
|
|
54
60
|
"IF OBJECT_ID(N'dbo.store', N'U') IS NULL" +
|
|
55
61
|
' BEGIN' +
|
|
@@ -59,6 +65,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
59
65
|
' );' +
|
|
60
66
|
' END';
|
|
61
67
|
|
|
68
|
+
// @ts-ignore
|
|
62
69
|
new mssql.ConnectionPool(this.settings).connect().then((pool) => {
|
|
63
70
|
this.db = pool;
|
|
64
71
|
|
|
@@ -74,7 +81,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
74
81
|
});
|
|
75
82
|
}
|
|
76
83
|
|
|
77
|
-
get(key, callback) {
|
|
84
|
+
get(key:string, callback:(err?:Error, value?:string)=>{}) {
|
|
78
85
|
const request = new mssql.Request(this.db);
|
|
79
86
|
|
|
80
87
|
request.input('key', mssql.NVarChar(100), key);
|
|
@@ -82,7 +89,8 @@ exports.Database = class extends AbstractDatabase {
|
|
|
82
89
|
request.query('SELECT [value] FROM [store] WHERE [key] = @key', (err, results) => {
|
|
83
90
|
let value = null;
|
|
84
91
|
|
|
85
|
-
if (!err && results.rowsAffected[0] === 1) {
|
|
92
|
+
if (!err && results && results.rowsAffected[0] === 1) {
|
|
93
|
+
// @ts-ignore
|
|
86
94
|
value = results.recordset[0].value;
|
|
87
95
|
}
|
|
88
96
|
|
|
@@ -90,7 +98,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
90
98
|
});
|
|
91
99
|
}
|
|
92
100
|
|
|
93
|
-
findKeys(key, notKey, callback) {
|
|
101
|
+
findKeys(key:string, notKey:string, callback:(err: Error | undefined, value:string[])=>{}) {
|
|
94
102
|
const request = new mssql.Request(this.db);
|
|
95
103
|
let query = 'SELECT [key] FROM [store] WHERE [key] LIKE @key';
|
|
96
104
|
|
|
@@ -107,11 +115,11 @@ exports.Database = class extends AbstractDatabase {
|
|
|
107
115
|
}
|
|
108
116
|
|
|
109
117
|
request.query(query, (err, results) => {
|
|
110
|
-
const value = [];
|
|
118
|
+
const value:string[] = [];
|
|
111
119
|
|
|
112
|
-
if (!err && results.rowsAffected[0] > 0) {
|
|
120
|
+
if (!err && results && results.rowsAffected[0] > 0) {
|
|
113
121
|
for (let i = 0; i < results.recordset.length; i++) {
|
|
114
|
-
value.push(results.recordset[i].key);
|
|
122
|
+
value.push((results.recordset[i] as RowResult).key);
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
125
|
|
|
@@ -119,7 +127,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
119
127
|
});
|
|
120
128
|
}
|
|
121
129
|
|
|
122
|
-
set(key, value, callback) {
|
|
130
|
+
set(key:string, value:string, callback: (val:string)=>{}) {
|
|
123
131
|
const request = new mssql.Request(this.db);
|
|
124
132
|
|
|
125
133
|
if (key.length > 100) {
|
|
@@ -135,23 +143,23 @@ exports.Database = class extends AbstractDatabase {
|
|
|
135
143
|
request.input('value', mssql.NText, value);
|
|
136
144
|
|
|
137
145
|
request.query(query, (err, info) => {
|
|
138
|
-
callback(err);
|
|
146
|
+
callback(err ? err.toString() : '');
|
|
139
147
|
});
|
|
140
148
|
}
|
|
141
149
|
}
|
|
142
150
|
|
|
143
|
-
remove(key, callback) {
|
|
151
|
+
remove(key:string, callback:()=>{}) {
|
|
144
152
|
const request = new mssql.Request(this.db);
|
|
145
153
|
request.input('key', mssql.NVarChar(100), key);
|
|
146
154
|
request.query('DELETE FROM [store] WHERE [key] = @key', callback);
|
|
147
155
|
}
|
|
148
156
|
|
|
149
|
-
doBulk(bulk, callback) {
|
|
157
|
+
doBulk(bulk: BulkObject[], callback:(err:any, results?: any)=>{}) {
|
|
150
158
|
const maxInserts = 100;
|
|
151
159
|
const request = new mssql.Request(this.db);
|
|
152
160
|
let firstReplace = true;
|
|
153
161
|
let firstRemove = true;
|
|
154
|
-
const replacements = [];
|
|
162
|
+
const replacements: string[] = [];
|
|
155
163
|
let removeSQL = 'DELETE FROM [store] WHERE [key] IN (';
|
|
156
164
|
|
|
157
165
|
for (const i in bulk) {
|
|
@@ -159,7 +167,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
159
167
|
if (firstReplace) {
|
|
160
168
|
replacements.push('BEGIN TRANSACTION;');
|
|
161
169
|
firstReplace = false;
|
|
162
|
-
} else if (i % maxInserts === 0) {
|
|
170
|
+
} else if (Number(i) % maxInserts === 0) {
|
|
163
171
|
replacements.push('\nCOMMIT TRANSACTION;\nBEGIN TRANSACTION;\n');
|
|
164
172
|
}
|
|
165
173
|
|
|
@@ -212,7 +220,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
212
220
|
);
|
|
213
221
|
}
|
|
214
222
|
|
|
215
|
-
close(callback) {
|
|
216
|
-
this.db.close(callback);
|
|
223
|
+
close(callback: (err?:Error)=>{}) {
|
|
224
|
+
this.db && this.db.close(callback);
|
|
217
225
|
}
|
|
218
226
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
'use strict';
|
|
2
1
|
/**
|
|
3
2
|
* 2011 Peter 'Pita' Martischka
|
|
4
3
|
*
|
|
@@ -15,12 +14,15 @@
|
|
|
15
14
|
* limitations under the License.
|
|
16
15
|
*/
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
import AbstractDatabase, {Settings} from '../lib/AbstractDatabase';
|
|
18
|
+
import mysql from 'mysql';
|
|
19
|
+
import util from 'util';
|
|
20
|
+
import {BulkObject} from './cassandra_db';
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
export const Database = class extends AbstractDatabase {
|
|
23
|
+
private _mysqlSettings: Settings;
|
|
24
|
+
private _pool: any;
|
|
25
|
+
constructor(settings:Settings) {
|
|
24
26
|
super();
|
|
25
27
|
this.logger = console;
|
|
26
28
|
this._mysqlSettings = {
|
|
@@ -39,19 +41,21 @@ exports.Database = class extends AbstractDatabase {
|
|
|
39
41
|
|
|
40
42
|
get isAsync() { return true; }
|
|
41
43
|
|
|
42
|
-
async _query(options) {
|
|
44
|
+
async _query(options: any):Promise<any> {
|
|
43
45
|
try {
|
|
44
46
|
return await new Promise((resolve, reject) => {
|
|
45
47
|
options = {timeout: this.settings.queryTimeout, ...options};
|
|
46
|
-
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
this._pool && this._pool.query(options, (err, ...args) => err != null ? reject(err) : resolve(args));
|
|
47
50
|
});
|
|
48
|
-
} catch (err) {
|
|
51
|
+
} catch (err:any) {
|
|
49
52
|
this.logger.error(`${err.fatal ? 'Fatal ' : ''}MySQL error: ${err.stack || err}`);
|
|
50
53
|
throw err;
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
async init() {
|
|
58
|
+
// @ts-ignore
|
|
55
59
|
this._pool = mysql.createPool(this._mysqlSettings);
|
|
56
60
|
const {database, charset} = this._mysqlSettings;
|
|
57
61
|
|
|
@@ -69,6 +73,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
69
73
|
const dbCharSet =
|
|
70
74
|
'SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME ' +
|
|
71
75
|
`FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = '${database}'`;
|
|
76
|
+
// @ts-ignore
|
|
72
77
|
let [result] = await this._query({sql: dbCharSet});
|
|
73
78
|
|
|
74
79
|
result = JSON.parse(JSON.stringify(result));
|
|
@@ -112,7 +117,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
112
117
|
}
|
|
113
118
|
}
|
|
114
119
|
|
|
115
|
-
async get(key) {
|
|
120
|
+
async get(key:string) {
|
|
116
121
|
const [results] = await this._query({
|
|
117
122
|
sql: 'SELECT `value` FROM `store` WHERE `key` = ? AND BINARY `key` = ?',
|
|
118
123
|
values: [key, key],
|
|
@@ -120,7 +125,7 @@ exports.Database = class extends AbstractDatabase {
|
|
|
120
125
|
return results.length === 1 ? results[0].value : null;
|
|
121
126
|
}
|
|
122
127
|
|
|
123
|
-
async findKeys(key, notKey) {
|
|
128
|
+
async findKeys(key:string, notKey:string) {
|
|
124
129
|
let query = 'SELECT `key` FROM `store` WHERE `key` LIKE ?';
|
|
125
130
|
const params = [];
|
|
126
131
|
|
|
@@ -135,22 +140,22 @@ exports.Database = class extends AbstractDatabase {
|
|
|
135
140
|
params.push(notKey);
|
|
136
141
|
}
|
|
137
142
|
const [results] = await this._query({sql: query, values: params});
|
|
138
|
-
return results.map((val) => val.key);
|
|
143
|
+
return results.map((val:{key:string}) => val.key);
|
|
139
144
|
}
|
|
140
145
|
|
|
141
|
-
async set(key, value) {
|
|
146
|
+
async set(key:string, value:string) {
|
|
142
147
|
if (key.length > 100) throw new Error('Your Key can only be 100 chars');
|
|
143
148
|
await this._query({sql: 'REPLACE INTO `store` VALUES (?,?)', values: [key, value]});
|
|
144
149
|
}
|
|
145
150
|
|
|
146
|
-
async remove(key) {
|
|
151
|
+
async remove(key:string) {
|
|
147
152
|
await this._query({
|
|
148
153
|
sql: 'DELETE FROM `store` WHERE `key` = ? AND BINARY `key` = ?',
|
|
149
154
|
values: [key, key],
|
|
150
155
|
});
|
|
151
156
|
}
|
|
152
157
|
|
|
153
|
-
async doBulk(bulk) {
|
|
158
|
+
async doBulk(bulk:BulkObject[]) {
|
|
154
159
|
const replaces = [];
|
|
155
160
|
const deletes = [];
|
|
156
161
|
for (const op of bulk) {
|