Skip to content

Commit 86bd271

Browse files
authored
Breaking: remove deprecated put, del & batch events (#104)
In favor of the `write` event. While still printing a warning if listeners are added for these events, because it's cheap and helps people who are upgrading. Category: removal
1 parent 5f621d4 commit 86bd271

10 files changed

+30
-250
lines changed

README.md

Lines changed: 0 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -856,8 +856,6 @@ Lastly, one way or another, every implementation _must_ support `data` of type S
856856

857857
An `abstract-level` database is an [`EventEmitter`](https://nodejs.org/api/events.html) and emits the events listed below.
858858

859-
The `put`, `del` and `batch` events are deprecated in favor of the `write` event and will be removed in a future version of `abstract-level`. If one or more `write` event listeners exist or if the [`prewrite`](#hook--dbhooksprewrite) hook is in use, either of which implies opting-in to the `write` event, then the deprecated events will not be emitted.
860-
861859
#### `opening`
862860

863861
Emitted when database is opening. Receives 0 arguments:
@@ -975,42 +973,6 @@ The same is true for `db.put()` and `db.del()`.
975973

976974
Emitted when a `db.clear()` call completed and entries were thus successfully deleted from the database. Receives a single `options` argument, which is the verbatim `options` argument that was passed to `db.clear(options)` (or an empty object if none) before having encoded range options.
977975

978-
#### `put` (deprecated)
979-
980-
Emitted when a `db.put()` call completed and an entry was thus successfully written to the database. Receives `key` and `value` arguments, which are the verbatim `key` and `value` that were passed to `db.put(key, value)` before having encoded them.
981-
982-
```js
983-
db.on('put', function (key, value) {
984-
console.log('Wrote', key, value)
985-
})
986-
```
987-
988-
#### `del` (deprecated)
989-
990-
Emitted when a `db.del()` call completed and an entry was thus successfully deleted from the database. Receives a single `key` argument, which is the verbatim `key` that was passed to `db.del(key)` before having encoded it.
991-
992-
```js
993-
db.on('del', function (key) {
994-
console.log('Deleted', key)
995-
})
996-
```
997-
998-
#### `batch` (deprecated)
999-
1000-
Emitted when a `db.batch([])` or chained `db.batch().write()` call completed and the data was thus successfully written to the database. Receives a single `operations` argument, which is the verbatim `operations` array that was passed to `db.batch(operations)` before having encoded it, or the equivalent for a chained `db.batch().write()`.
1001-
1002-
```js
1003-
db.on('batch', function (operations) {
1004-
for (const op of operations) {
1005-
if (op.type === 'put') {
1006-
console.log('Wrote', op.key, op.value)
1007-
} else {
1008-
console.log('Deleted', op.key)
1009-
}
1010-
}
1011-
})
1012-
```
1013-
1014976
### Order Of Operations
1015977

1016978
There is no defined order between parallel write operations. Consider:

abstract-chained-batch.js

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ class AbstractChainedBatch {
1414
#length = 0
1515
#closePromise = null
1616
#publicOperations
17-
#legacyOperations
1817
#prewriteRun
1918
#prewriteBatch
2019
#prewriteData
@@ -33,11 +32,6 @@ class AbstractChainedBatch {
3332
// operations, which is the expensive part) if there are 0 write event listeners.
3433
this.#publicOperations = enableWriteEvent ? [] : null
3534

36-
// Operations for legacy batch event. If user opted-in to write event or prewrite
37-
// hook, skip legacy batch event. We can't skip the batch event based on listener
38-
// count, because a listener may be added between put() or del() and write().
39-
this.#legacyOperations = enableWriteEvent || enablePrewriteHook ? null : []
40-
4135
this.#addMode = getOptions(options, emptyOptions).add === true
4236

4337
if (enablePrewriteHook) {
@@ -73,7 +67,6 @@ class AbstractChainedBatch {
7367

7468
const delegated = options.sublevel != null
7569
const db = delegated ? options.sublevel : this.db
76-
const original = options
7770

7871
db._assertValidKey(key)
7972
db._assertValidValue(value)
@@ -146,14 +139,6 @@ class AbstractChainedBatch {
146139
}
147140

148141
this.#publicOperations.push(publicOperation)
149-
} else if (this.#legacyOperations !== null && !siblings) {
150-
const legacyOperation = { ...original }
151-
152-
legacyOperation.type = 'put'
153-
legacyOperation.key = key
154-
legacyOperation.value = value
155-
156-
this.#legacyOperations.push(legacyOperation)
157142
}
158143

159144
// If we're forwarding the sublevel option then don't prefix the key yet
@@ -182,7 +167,6 @@ class AbstractChainedBatch {
182167

183168
const delegated = options.sublevel != null
184169
const db = delegated ? options.sublevel : this.db
185-
const original = options
186170

187171
db._assertValidKey(key)
188172

@@ -228,13 +212,6 @@ class AbstractChainedBatch {
228212
}
229213

230214
this.#publicOperations.push(publicOperation)
231-
} else if (this.#legacyOperations !== null) {
232-
const legacyOperation = { ...original }
233-
234-
legacyOperation.type = 'del'
235-
legacyOperation.key = key
236-
237-
this.#legacyOperations.push(legacyOperation)
238215
}
239216

240217
op.key = this.db.prefixKey(encodedKey, keyFormat, true)
@@ -261,7 +238,6 @@ class AbstractChainedBatch {
261238
this._clear()
262239

263240
if (this.#publicOperations !== null) this.#publicOperations = []
264-
if (this.#legacyOperations !== null) this.#legacyOperations = []
265241
if (this.#prewriteData !== null) this.#prewriteData.clear()
266242

267243
this.#length = 0
@@ -330,8 +306,6 @@ class AbstractChainedBatch {
330306
// db close which in turn triggers (idempotently) closing this batch.
331307
if (this.#publicOperations !== null) {
332308
this.db.emit('write', this.#publicOperations)
333-
} else if (this.#legacyOperations !== null) {
334-
this.db.emit('batch', this.#legacyOperations)
335309
}
336310

337311
return this.#closePromise

abstract-level.js

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -64,21 +64,11 @@ class AbstractLevel extends EventEmitter {
6464
closing: true,
6565
closed: true,
6666
write: true,
67-
put: true,
68-
del: true,
69-
batch: true,
7067
clear: true
7168
}
7269
})
7370

74-
// Monitor event listeners
75-
this.#eventMonitor = new EventMonitor(this, [
76-
{ name: 'write' },
77-
{ name: 'put', deprecated: true, alt: 'write' },
78-
{ name: 'del', deprecated: true, alt: 'write' },
79-
{ name: 'batch', deprecated: true, alt: 'write' }
80-
])
81-
71+
this.#eventMonitor = new EventMonitor(this)
8272
this.#transcoder = new Transcoder(formats(this))
8373
this.#keyEncoding = this.#transcoder.encoding(keyEncoding || 'utf8')
8474
this.#valueEncoding = this.#transcoder.encoding(valueEncoding || 'utf8')
@@ -578,9 +568,6 @@ class AbstractLevel extends EventEmitter {
578568
}
579569

580570
this.emit('write', [op])
581-
} else {
582-
// TODO (semver-major): remove
583-
this.emit('put', key, value)
584571
}
585572
}
586573

@@ -629,9 +616,6 @@ class AbstractLevel extends EventEmitter {
629616
}
630617

631618
this.emit('write', [op])
632-
} else {
633-
// TODO (semver-major): remove
634-
this.emit('del', key)
635619
}
636620
}
637621

@@ -782,9 +766,6 @@ class AbstractLevel extends EventEmitter {
782766

783767
if (enableWriteEvent) {
784768
this.emit('write', publicOperations)
785-
} else if (!enablePrewriteHook) {
786-
// TODO (semver-major): remove
787-
this.emit('batch', operations)
788769
}
789770
}
790771

lib/event-monitor.js

Lines changed: 16 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,28 @@
33
const { deprecate } = require('./common')
44

55
exports.EventMonitor = class EventMonitor {
6-
constructor (emitter, events) {
7-
for (const event of events) {
8-
// Track whether listeners are present
9-
this[event.name] = false
10-
11-
// Prepare deprecation message
12-
if (event.deprecated) {
13-
event.message = `The '${event.name}' event is deprecated in favor of '${event.alt}' and will be removed in a future version of abstract-level`
6+
constructor (emitter) {
7+
// Track whether listeners are present, because checking
8+
// a boolean is faster than checking listenerCount().
9+
this.write = false
10+
11+
const beforeAdded = (name) => {
12+
if (name === 'write') {
13+
this.write = true
1414
}
15-
}
16-
17-
const map = new Map(events.map(e => [e.name, e]))
18-
const monitor = this
19-
20-
emitter.on('newListener', beforeAdded)
21-
emitter.on('removeListener', afterRemoved)
2215

23-
function beforeAdded (name) {
24-
const event = map.get(name)
25-
26-
if (event !== undefined) {
27-
monitor[name] = true
28-
29-
if (event.deprecated) {
30-
deprecate(event.message)
31-
}
16+
if (name === 'put' || name === 'del' || name === 'batch') {
17+
deprecate(`The '${name}' event has been removed in favor of 'write'`)
3218
}
3319
}
3420

35-
function afterRemoved (name) {
36-
if (map.has(name)) {
37-
monitor[name] = this.listenerCount(name) > 0
21+
const afterRemoved = (name) => {
22+
if (name === 'write') {
23+
this.write = emitter.listenerCount('write') > 0
3824
}
3925
}
26+
27+
emitter.on('newListener', beforeAdded)
28+
emitter.on('removeListener', afterRemoved)
4029
}
4130
}

test/batch-test.js

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -199,24 +199,6 @@ exports.atomic = function (test, testCommon) {
199199
})
200200
}
201201

202-
exports.events = function (test, testCommon) {
203-
test('batch([]) emits batch event', async function (t) {
204-
t.plan(2)
205-
206-
const db = testCommon.factory()
207-
await db.open()
208-
209-
t.ok(db.supports.events.batch)
210-
211-
db.on('batch', function (ops) {
212-
t.same(ops, [{ type: 'put', key: 456, value: 99, custom: 123 }])
213-
})
214-
215-
await db.batch([{ type: 'put', key: 456, value: 99, custom: 123 }])
216-
return db.close()
217-
})
218-
}
219-
220202
exports.tearDown = function (test, testCommon) {
221203
test('batch([]) teardown', async function (t) {
222204
return db.close()
@@ -228,6 +210,5 @@ exports.all = function (test, testCommon) {
228210
exports.args(test, testCommon)
229211
exports.batch(test, testCommon)
230212
exports.atomic(test, testCommon)
231-
exports.events(test, testCommon)
232213
exports.tearDown(test, testCommon)
233214
}

test/chained-batch-test.js

Lines changed: 10 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,15 @@ exports.batch = function (test, testCommon) {
239239
const db = testCommon.factory()
240240
await db.open()
241241

242-
db.once('batch', function (operations) {
242+
const utf8 = db.keyEncoding('utf8')
243+
const json = db.valueEncoding('json')
244+
245+
db.once('write', function (operations) {
243246
t.same(operations, [
244-
{ type: 'put', key: 'a', value: 'a', valueEncoding: 'json' },
245-
{ type: 'put', key: 'b', value: 'b' },
246-
{ type: 'put', key: '"c"', value: 'c' },
247-
{ type: 'del', key: 'c', keyEncoding: 'json', arbitraryOption: true }
247+
{ type: 'put', key: 'a', value: 'a', keyEncoding: utf8, valueEncoding: json, encodedKey: 'a', encodedValue: '"a"' },
248+
{ type: 'put', key: 'b', value: 'b', keyEncoding: utf8, valueEncoding: utf8, encodedKey: 'b', encodedValue: 'b' },
249+
{ type: 'put', key: '"c"', value: 'c', keyEncoding: utf8, valueEncoding: utf8, encodedKey: '"c"', encodedValue: 'c' },
250+
{ type: 'del', key: 'c', keyEncoding: json, encodedKey: '"c"', arbitraryOption: true }
248251
])
249252
})
250253

@@ -265,32 +268,13 @@ exports.batch = function (test, testCommon) {
265268
}
266269

267270
exports.events = function (test, testCommon) {
268-
test('chained batch emits batch event', async function (t) {
269-
t.plan(2)
270-
271-
const db = testCommon.factory()
272-
await db.open()
273-
274-
t.ok(db.supports.events.batch)
275-
276-
db.on('batch', function (ops) {
277-
t.same(ops, [
278-
{ type: 'put', key: 987, value: 'b', custom: 123 },
279-
{ type: 'del', key: 216, custom: 999 }
280-
])
281-
})
282-
283-
await db.batch().put(987, 'b', { custom: 123 }).del(216, { custom: 999 }).write()
284-
await db.close()
285-
})
286-
287-
test('db.close() on chained batch event', async function (t) {
271+
test('db.close() on chained batch write event', async function (t) {
288272
const db = testCommon.factory()
289273
await db.open()
290274

291275
let promise
292276

293-
db.on('batch', function () {
277+
db.on('write', function () {
294278
// Should not interfere with the current write() operation
295279
promise = db.close()
296280
})

test/del-test.js

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -41,34 +41,16 @@ exports.del = function (test, testCommon) {
4141

4242
traits.open('del()', testCommon, async function (t, db) {
4343
let emitted = false
44-
db.once('del', () => { emitted = true })
45-
t.is(await assertPromise(db.del('foo')), undefined, 'void promise')
46-
t.ok(emitted)
44+
db.once('write', () => { emitted = true })
45+
t.is(await db.del('foo'), undefined, 'void promise')
46+
t.ok(emitted) // Not sure what the purpose of this test is
4747
})
4848

4949
traits.closed('del()', testCommon, async function (t, db) {
5050
return db.del('foo')
5151
})
5252
}
5353

54-
exports.events = function (test, testCommon) {
55-
test('del() emits del event', async function (t) {
56-
t.plan(2)
57-
58-
const db = testCommon.factory()
59-
await db.open()
60-
61-
t.ok(db.supports.events.del)
62-
63-
db.on('del', function (key) {
64-
t.is(key, 456)
65-
})
66-
67-
await db.del(456)
68-
return db.close()
69-
})
70-
}
71-
7254
exports.tearDown = function (test, testCommon) {
7355
test('del() teardown', async function (t) {
7456
return db.close()
@@ -79,6 +61,5 @@ exports.all = function (test, testCommon) {
7961
exports.setUp(test, testCommon)
8062
exports.args(test, testCommon)
8163
exports.del(test, testCommon)
82-
exports.events(test, testCommon)
8364
exports.tearDown(test, testCommon)
8465
}

0 commit comments

Comments
 (0)