rocksdb-native 3.0.1 → 3.1.0
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/index.js +28 -37
- package/lib/batch.js +49 -34
- package/lib/iterator.js +14 -20
- package/lib/state.js +26 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
const { ReadBatch, WriteBatch } = require('./lib/batch')
|
|
2
1
|
const ColumnFamily = require('./lib/column-family')
|
|
3
2
|
const Iterator = require('./lib/iterator')
|
|
4
3
|
const Snapshot = require('./lib/snapshot')
|
|
@@ -9,12 +8,16 @@ class RocksDB {
|
|
|
9
8
|
const {
|
|
10
9
|
columnFamily,
|
|
11
10
|
state = new DBState(this, path, opts),
|
|
12
|
-
snapshot = null
|
|
11
|
+
snapshot = null,
|
|
12
|
+
keyEncoding = null,
|
|
13
|
+
valueEncoding = null
|
|
13
14
|
} = opts
|
|
14
15
|
|
|
15
16
|
this._state = state
|
|
16
17
|
this._snapshot = snapshot
|
|
17
18
|
this._columnFamily = state.getColumnFamily(columnFamily)
|
|
19
|
+
this._keyEncoding = keyEncoding
|
|
20
|
+
this._valueEncoding = valueEncoding
|
|
18
21
|
this._index = this._state.addSession(this)
|
|
19
22
|
}
|
|
20
23
|
|
|
@@ -36,7 +39,9 @@ class RocksDB {
|
|
|
36
39
|
|
|
37
40
|
session({
|
|
38
41
|
columnFamily = this._columnFamily,
|
|
39
|
-
snapshot = this._snapshot !== null
|
|
42
|
+
snapshot = this._snapshot !== null,
|
|
43
|
+
keyEncoding = this._keyEncoding,
|
|
44
|
+
valueEncoding = this._valueEncoding
|
|
40
45
|
} = {}) {
|
|
41
46
|
let snap = null
|
|
42
47
|
|
|
@@ -49,12 +54,14 @@ class RocksDB {
|
|
|
49
54
|
return new RocksDB(null, {
|
|
50
55
|
state: this._state,
|
|
51
56
|
columnFamily,
|
|
52
|
-
snapshot: snap
|
|
57
|
+
snapshot: snap,
|
|
58
|
+
keyEncoding,
|
|
59
|
+
valueEncoding
|
|
53
60
|
})
|
|
54
61
|
}
|
|
55
62
|
|
|
56
|
-
columnFamily(name) {
|
|
57
|
-
return this.session({ columnFamily: name })
|
|
63
|
+
columnFamily(name, opts) {
|
|
64
|
+
return this.session({ ...opts, columnFamily: name })
|
|
58
65
|
}
|
|
59
66
|
|
|
60
67
|
snapshot() {
|
|
@@ -114,52 +121,36 @@ class RocksDB {
|
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
read(opts) {
|
|
117
|
-
return
|
|
124
|
+
return this._state.createReadBatch(this, opts)
|
|
118
125
|
}
|
|
119
126
|
|
|
120
127
|
write(opts) {
|
|
121
|
-
return
|
|
128
|
+
return this._state.createWriteBatch(this, opts)
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
async get(key, opts) {
|
|
125
|
-
const batch = this.read({ ...opts, capacity: 1 })
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
return await value
|
|
130
|
-
} finally {
|
|
131
|
-
batch.destroy()
|
|
132
|
-
}
|
|
132
|
+
const batch = this.read({ ...opts, capacity: 1, autoDestroy: true })
|
|
133
|
+
const value = batch.get(key)
|
|
134
|
+
batch.tryFlush()
|
|
135
|
+
return value
|
|
133
136
|
}
|
|
134
137
|
|
|
135
138
|
async put(key, value, opts) {
|
|
136
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await batch.flush()
|
|
140
|
-
} finally {
|
|
141
|
-
batch.destroy()
|
|
142
|
-
}
|
|
139
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
140
|
+
batch.tryPut(key, value)
|
|
141
|
+
await batch.flush()
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
async delete(key, opts) {
|
|
146
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
await batch.flush()
|
|
150
|
-
} finally {
|
|
151
|
-
batch.destroy()
|
|
152
|
-
}
|
|
145
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
146
|
+
batch.tryDelete(key)
|
|
147
|
+
await batch.flush()
|
|
153
148
|
}
|
|
154
149
|
|
|
155
150
|
async deleteRange(start, end, opts) {
|
|
156
|
-
const batch = this.write({ ...opts, capacity: 1 })
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
await batch.flush()
|
|
160
|
-
} finally {
|
|
161
|
-
batch.destroy()
|
|
162
|
-
}
|
|
151
|
+
const batch = this.write({ ...opts, capacity: 1, autoDestroy: true })
|
|
152
|
+
batch.tryDeleteRange(start, end)
|
|
153
|
+
await batch.flush()
|
|
163
154
|
}
|
|
164
155
|
}
|
|
165
156
|
|
package/lib/batch.js
CHANGED
|
@@ -6,26 +6,16 @@ const resolved = Promise.resolve()
|
|
|
6
6
|
|
|
7
7
|
class RocksDBBatch {
|
|
8
8
|
constructor(db, opts = {}) {
|
|
9
|
-
const {
|
|
10
|
-
columnFamily = db.defaultColumnFamily,
|
|
11
|
-
capacity = 8,
|
|
12
|
-
encoding = null,
|
|
13
|
-
keyEncoding = encoding,
|
|
14
|
-
valueEncoding = encoding
|
|
15
|
-
} = opts
|
|
9
|
+
const { capacity = 8, autoDestroy = false } = opts
|
|
16
10
|
|
|
17
11
|
db._state.ref()
|
|
18
12
|
|
|
19
|
-
this.
|
|
20
|
-
this._columnFamily = columnFamily
|
|
13
|
+
this._db = db
|
|
21
14
|
this._destroyed = false
|
|
22
15
|
this._capacity = capacity
|
|
23
16
|
this._operations = []
|
|
24
17
|
this._promises = []
|
|
25
18
|
|
|
26
|
-
this._keyEncoding = keyEncoding
|
|
27
|
-
this._valueEncoding = valueEncoding
|
|
28
|
-
|
|
29
19
|
this._enqueuePromise = this._enqueuePromise.bind(this)
|
|
30
20
|
|
|
31
21
|
this._request = null
|
|
@@ -33,8 +23,19 @@ class RocksDBBatch {
|
|
|
33
23
|
|
|
34
24
|
this._handle = null
|
|
35
25
|
this._buffer = null
|
|
26
|
+
this._autoDestroy = autoDestroy
|
|
27
|
+
|
|
28
|
+
if (db._state.opened === true) this.ready()
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_reuse(db, opts = {}) {
|
|
32
|
+
const { autoDestroy = false } = opts
|
|
33
|
+
|
|
34
|
+
db._state.ref()
|
|
36
35
|
|
|
37
|
-
|
|
36
|
+
this._db = db
|
|
37
|
+
this._destroyed = false
|
|
38
|
+
this._autoDestroy = autoDestroy
|
|
38
39
|
}
|
|
39
40
|
|
|
40
41
|
_onfinished() {
|
|
@@ -45,6 +46,7 @@ class RocksDBBatch {
|
|
|
45
46
|
this._request = null
|
|
46
47
|
this._resolve = null
|
|
47
48
|
|
|
49
|
+
if (this._autoDestroy === true) this.destroy()
|
|
48
50
|
if (resolve !== null) resolve()
|
|
49
51
|
}
|
|
50
52
|
|
|
@@ -61,7 +63,7 @@ class RocksDBBatch {
|
|
|
61
63
|
async ready() {
|
|
62
64
|
if (this._handle !== null) return
|
|
63
65
|
|
|
64
|
-
if (this._state.opened === false) await this._state.ready()
|
|
66
|
+
if (this._db._state.opened === false) await this._db._state.ready()
|
|
65
67
|
|
|
66
68
|
this._init()
|
|
67
69
|
}
|
|
@@ -72,7 +74,22 @@ class RocksDBBatch {
|
|
|
72
74
|
|
|
73
75
|
this._destroyed = true
|
|
74
76
|
|
|
75
|
-
this.
|
|
77
|
+
if (this._promises.length) this._abort()
|
|
78
|
+
|
|
79
|
+
this._db._state.unref()
|
|
80
|
+
this._onfree()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
_onfree() {
|
|
84
|
+
this._db._state.freeBatch(this, false)
|
|
85
|
+
this._db = null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
_abort() {
|
|
89
|
+
for (let i = 0; i < this._promises.length; i++) {
|
|
90
|
+
const promise = this._promises[i]
|
|
91
|
+
if (promise !== null) promise.reject(new Error('Batch is destroyed'))
|
|
92
|
+
}
|
|
76
93
|
}
|
|
77
94
|
|
|
78
95
|
flush() {
|
|
@@ -105,31 +122,25 @@ class RocksDBBatch {
|
|
|
105
122
|
}
|
|
106
123
|
|
|
107
124
|
_encodeKey(k) {
|
|
108
|
-
if (this._keyEncoding) return c.encode(this._keyEncoding, k)
|
|
125
|
+
if (this._db._keyEncoding) return c.encode(this._db._keyEncoding, k)
|
|
109
126
|
if (typeof k === 'string') return Buffer.from(k)
|
|
110
127
|
return k
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
_encodeValue(v) {
|
|
114
|
-
if (this._valueEncoding) return c.encode(this._valueEncoding, v)
|
|
131
|
+
if (this._db._valueEncoding) return c.encode(this._db._valueEncoding, v)
|
|
115
132
|
if (v === null) return empty
|
|
116
133
|
if (typeof v === 'string') return Buffer.from(v)
|
|
117
134
|
return v
|
|
118
135
|
}
|
|
119
136
|
|
|
120
137
|
_decodeValue(b) {
|
|
121
|
-
if (this._valueEncoding) return c.decode(this._valueEncoding, b)
|
|
138
|
+
if (this._db._valueEncoding) return c.decode(this._db._valueEncoding, b)
|
|
122
139
|
return b
|
|
123
140
|
}
|
|
124
141
|
}
|
|
125
142
|
|
|
126
143
|
exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
127
|
-
constructor(db, opts) {
|
|
128
|
-
super(db, opts)
|
|
129
|
-
|
|
130
|
-
this._snapshot = db._snapshot
|
|
131
|
-
}
|
|
132
|
-
|
|
133
144
|
_init() {
|
|
134
145
|
this._handle = binding.readInit()
|
|
135
146
|
this._buffer = binding.readBuffer(this._handle, this._capacity)
|
|
@@ -145,10 +156,10 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
|
145
156
|
await super._flush()
|
|
146
157
|
|
|
147
158
|
binding.read(
|
|
148
|
-
this._state.handle,
|
|
159
|
+
this._db._state.handle,
|
|
149
160
|
this._handle,
|
|
150
161
|
this._operations,
|
|
151
|
-
this._snapshot ? this._snapshot._handle : null,
|
|
162
|
+
this._db._snapshot ? this._db._snapshot._handle : null,
|
|
152
163
|
this,
|
|
153
164
|
this._onread
|
|
154
165
|
)
|
|
@@ -179,7 +190,7 @@ exports.ReadBatch = class RocksDBReadBatch extends RocksDBBatch {
|
|
|
179
190
|
const promise = new Promise(this._enqueuePromise)
|
|
180
191
|
|
|
181
192
|
this._operations.push(
|
|
182
|
-
new RocksDBGet(this._encodeKey(key), this._columnFamily)
|
|
193
|
+
new RocksDBGet(this._encodeKey(key), this._db._columnFamily)
|
|
183
194
|
)
|
|
184
195
|
|
|
185
196
|
this._resize()
|
|
@@ -200,11 +211,15 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
200
211
|
}
|
|
201
212
|
}
|
|
202
213
|
|
|
214
|
+
_onfree() {
|
|
215
|
+
this._db._state.freeBatch(this, true)
|
|
216
|
+
}
|
|
217
|
+
|
|
203
218
|
async _flush() {
|
|
204
219
|
await super._flush()
|
|
205
220
|
|
|
206
221
|
binding.write(
|
|
207
|
-
this._state.handle,
|
|
222
|
+
this._db._state.handle,
|
|
208
223
|
this._handle,
|
|
209
224
|
this._operations,
|
|
210
225
|
this,
|
|
@@ -233,7 +248,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
233
248
|
new RocksDBPut(
|
|
234
249
|
this._encodeKey(key),
|
|
235
250
|
this._encodeValue(value),
|
|
236
|
-
this._columnFamily
|
|
251
|
+
this._db._columnFamily
|
|
237
252
|
)
|
|
238
253
|
)
|
|
239
254
|
|
|
@@ -249,7 +264,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
249
264
|
new RocksDBPut(
|
|
250
265
|
this._encodeKey(key),
|
|
251
266
|
this._encodeValue(value),
|
|
252
|
-
this._columnFamily
|
|
267
|
+
this._db._columnFamily
|
|
253
268
|
)
|
|
254
269
|
)
|
|
255
270
|
|
|
@@ -264,7 +279,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
264
279
|
const promise = new Promise(this._enqueuePromise)
|
|
265
280
|
|
|
266
281
|
this._operations.push(
|
|
267
|
-
new RocksDBDelete(this._encodeKey(key), this._columnFamily)
|
|
282
|
+
new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
|
|
268
283
|
)
|
|
269
284
|
|
|
270
285
|
this._resize()
|
|
@@ -276,7 +291,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
276
291
|
if (this._request) throw new Error('Request already in progress')
|
|
277
292
|
|
|
278
293
|
this._operations.push(
|
|
279
|
-
new RocksDBDelete(this._encodeKey(key), this._columnFamily)
|
|
294
|
+
new RocksDBDelete(this._encodeKey(key), this._db._columnFamily)
|
|
280
295
|
)
|
|
281
296
|
|
|
282
297
|
this._promises.push(null)
|
|
@@ -293,7 +308,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
293
308
|
new RocksDBDeleteRange(
|
|
294
309
|
this._encodeKey(start),
|
|
295
310
|
this._encodeKey(end),
|
|
296
|
-
this._columnFamily
|
|
311
|
+
this._db._columnFamily
|
|
297
312
|
)
|
|
298
313
|
)
|
|
299
314
|
|
|
@@ -309,7 +324,7 @@ exports.WriteBatch = class RocksDBWriteBatch extends RocksDBBatch {
|
|
|
309
324
|
new RocksDBDeleteRange(
|
|
310
325
|
this._encodeKey(start),
|
|
311
326
|
this._encodeKey(end),
|
|
312
|
-
this._columnFamily
|
|
327
|
+
this._db._columnFamily
|
|
313
328
|
)
|
|
314
329
|
)
|
|
315
330
|
|
package/lib/iterator.js
CHANGED
|
@@ -7,28 +7,20 @@ const empty = Buffer.alloc(0)
|
|
|
7
7
|
module.exports = class RocksDBIterator extends Readable {
|
|
8
8
|
constructor(db, opts = {}) {
|
|
9
9
|
const {
|
|
10
|
-
columnFamily = db.defaultColumnFamily,
|
|
11
10
|
gt = null,
|
|
12
11
|
gte = null,
|
|
13
12
|
lt = null,
|
|
14
13
|
lte = null,
|
|
15
14
|
reverse = false,
|
|
16
15
|
limit = Infinity,
|
|
17
|
-
capacity = 8
|
|
18
|
-
encoding = null,
|
|
19
|
-
keyEncoding = encoding,
|
|
20
|
-
valueEncoding = encoding
|
|
16
|
+
capacity = 8
|
|
21
17
|
} = opts
|
|
22
18
|
|
|
23
19
|
super()
|
|
24
20
|
|
|
25
21
|
db._state.ref()
|
|
26
22
|
|
|
27
|
-
this.
|
|
28
|
-
this._columnFamily = columnFamily
|
|
29
|
-
|
|
30
|
-
this._keyEncoding = keyEncoding
|
|
31
|
-
this._valueEncoding = valueEncoding
|
|
23
|
+
this._db = db
|
|
32
24
|
|
|
33
25
|
this._gt = gt ? this._encodeKey(gt) : empty
|
|
34
26
|
this._gte = gte ? this._encodeKey(gte) : empty
|
|
@@ -38,7 +30,6 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
38
30
|
this._reverse = reverse
|
|
39
31
|
this._limit = limit < 0 ? Infinity : limit
|
|
40
32
|
this._capacity = capacity
|
|
41
|
-
this._snapshot = db._snapshot
|
|
42
33
|
|
|
43
34
|
this._pendingOpen = null
|
|
44
35
|
this._pendingRead = null
|
|
@@ -47,7 +38,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
47
38
|
this._buffer = null
|
|
48
39
|
this._handle = null
|
|
49
40
|
|
|
50
|
-
if (this._state.opened === true) this.ready()
|
|
41
|
+
if (this._db._state.opened === true) this.ready()
|
|
51
42
|
}
|
|
52
43
|
|
|
53
44
|
_onopen(err) {
|
|
@@ -80,7 +71,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
80
71
|
_onclose(err) {
|
|
81
72
|
const cb = this._pendingDestroy
|
|
82
73
|
this._pendingDestroy = null
|
|
83
|
-
this._state.unref()
|
|
74
|
+
this._db._state.unref()
|
|
84
75
|
cb(err)
|
|
85
76
|
}
|
|
86
77
|
|
|
@@ -93,7 +84,7 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
93
84
|
async ready() {
|
|
94
85
|
if (this._handle !== null) return
|
|
95
86
|
|
|
96
|
-
if (this._state.opened === false) await this._state.ready()
|
|
87
|
+
if (this._db._state.opened === false) await this._db._state.ready()
|
|
97
88
|
|
|
98
89
|
this._init()
|
|
99
90
|
}
|
|
@@ -109,15 +100,15 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
109
100
|
this._pendingOpen = cb
|
|
110
101
|
|
|
111
102
|
binding.iteratorOpen(
|
|
112
|
-
this._state.handle,
|
|
103
|
+
this._db._state.handle,
|
|
113
104
|
this._handle,
|
|
114
|
-
this._columnFamily._handle,
|
|
105
|
+
this._db._columnFamily._handle,
|
|
115
106
|
this._gt,
|
|
116
107
|
this._gte,
|
|
117
108
|
this._lt,
|
|
118
109
|
this._lte,
|
|
119
110
|
this._reverse,
|
|
120
|
-
this._snapshot ? this._snapshot._handle : null,
|
|
111
|
+
this._db._snapshot ? this._db._snapshot._handle : null,
|
|
121
112
|
this,
|
|
122
113
|
this._onopen,
|
|
123
114
|
this._onclose,
|
|
@@ -140,18 +131,21 @@ module.exports = class RocksDBIterator extends Readable {
|
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
_encodeKey(k) {
|
|
143
|
-
if (this._keyEncoding
|
|
134
|
+
if (this._db._keyEncoding !== null)
|
|
135
|
+
return c.encode(this._db._keyEncoding, k)
|
|
144
136
|
if (typeof k === 'string') return Buffer.from(k)
|
|
145
137
|
return k
|
|
146
138
|
}
|
|
147
139
|
|
|
148
140
|
_decodeKey(b) {
|
|
149
|
-
if (this._keyEncoding
|
|
141
|
+
if (this._db._keyEncoding !== null)
|
|
142
|
+
return c.decode(this._db._keyEncoding, b)
|
|
150
143
|
return b
|
|
151
144
|
}
|
|
152
145
|
|
|
153
146
|
_decodeValue(b) {
|
|
154
|
-
if (this._valueEncoding
|
|
147
|
+
if (this._db._valueEncoding !== null)
|
|
148
|
+
return c.decode(this._db._valueEncoding, b)
|
|
155
149
|
return b
|
|
156
150
|
}
|
|
157
151
|
}
|
package/lib/state.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
const ReadyResource = require('ready-resource')
|
|
2
2
|
const RefCounter = require('refcounter')
|
|
3
|
+
const { ReadBatch, WriteBatch } = require('./batch')
|
|
3
4
|
const ColumnFamily = require('./column-family')
|
|
4
5
|
const binding = require('../binding')
|
|
5
6
|
|
|
7
|
+
const MAX_BATCH_REUSE = 64
|
|
8
|
+
|
|
6
9
|
module.exports = class DBState extends ReadyResource {
|
|
7
10
|
constructor(db, path, opts) {
|
|
8
11
|
super()
|
|
@@ -28,6 +31,8 @@ module.exports = class DBState extends ReadyResource {
|
|
|
28
31
|
this._suspending = null
|
|
29
32
|
this._resuming = null
|
|
30
33
|
this._columnsFlushed = false
|
|
34
|
+
this._readBatches = []
|
|
35
|
+
this._writeBatches = []
|
|
31
36
|
|
|
32
37
|
for (const col of columnFamilies) {
|
|
33
38
|
this.columnFamilies.push(
|
|
@@ -47,9 +52,29 @@ module.exports = class DBState extends ReadyResource {
|
|
|
47
52
|
)
|
|
48
53
|
}
|
|
49
54
|
|
|
55
|
+
createReadBatch(db, opts) {
|
|
56
|
+
if (this._readBatches.length === 0) return new ReadBatch(db, opts)
|
|
57
|
+
const batch = this._readBatches.pop()
|
|
58
|
+
batch._reuse(db, opts)
|
|
59
|
+
return batch
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
createWriteBatch(db, opts) {
|
|
63
|
+
if (this._writeBatches.length === 0) return new WriteBatch(db, opts)
|
|
64
|
+
const batch = this._writeBatches.pop()
|
|
65
|
+
batch._reuse(db, opts)
|
|
66
|
+
return batch
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
freeBatch(batch, writable) {
|
|
70
|
+
const queue = writable ? this._writeBatches : this._readBatches
|
|
71
|
+
if (queue.length >= MAX_BATCH_REUSE) return
|
|
72
|
+
queue.push(batch)
|
|
73
|
+
}
|
|
74
|
+
|
|
50
75
|
addSession(db) {
|
|
51
76
|
this.sessionRefs.inc()
|
|
52
|
-
|
|
77
|
+
return this.sessions.push(db) - 1
|
|
53
78
|
}
|
|
54
79
|
|
|
55
80
|
removeSession(db) {
|