Conversation
Adds postopen, prewrite and newsub hooks that allow userland "hook
functions" to customize behavior of the database. See README for
details. A quick example:
```js
db.hooks.prewrite.add(function (op, batch) {
if (op.type === 'put') {
batch.add({
type: 'put',
key: op.value.foo,
value: op.key,
sublevel: fooIndex
})
}
})
```
More generally, this is a move towards "renewed modularity". Our
ecosystem is old and many modules no longer work because they had
no choice but to monkeypatch database methods, of which the
signature has changed since then.
So in addition to hooks, this:
- Introduces a new `write` event that is emitted on `db.batch()`,
`db.put()` and `db.del()` and has richer data: userland options,
encoded data, keyEncoding and valueEncoding. The `batch`, `put`
and `del` events are now deprecated and will be removed in a
future version. Related to Level/level#222.
- Restores support of userland options on batch operations. In
particular, to copy options in `db.batch(ops, options)` to ops,
allowing for code like `db.batch(ops, { ttl: 123 })` to apply a
default userland `ttl` option to all ops.
No breaking changes, yet. Using hooks means opting-in to new
behaviors (like the new write event) and disables some old behaviors
(like the deprecated events). Later on we can make those the default
behavior, regardless of whether hooks are used.
TODO: benchmarks, tests and optionally some light refactoring.
Closes Level/community#44.
|
Initial batch benchmarks (on |
|
for (let i = 0; i < 100; i++) {
db.hooks.prewrite.add(function () {})
} |
|
In |
And simplify existing tests by first checking when the hook function is called, i.e. after db has opened.
|
There's one remaining issue to fix (or not). If you do: const data = db.sublevel('data')
const users = data.sublevel('users')
data.on('write', function (ops) {
const wrongKey = ops[0].key
})
data.batch().del('alice', { sublevel: users })Then the |
|
I have a solution and a PoC implementation, but it'll hurt performance for nested sublevels. Given I have to benchmark that and see what tweaks can be made, but even if performance is significantly worse (and I think it will be) it might be worth it. Because it benefits both events and hooks: It would make this PR semver-major, for two reasons:
In which case, I might just remove the |
|
@juliangruber @ralphtheninja any objections? The |
Results for Click to expandAt a depth of 2 sublevels, the difference between With support of Click to expand |
|
I've created a |
|
Sorry @vweevers, I don't have time to review this ATM :| |
|
OK! Thanks for letting me know. FWIW I'll probably mark the hooks API as experimental (before v2 goes out the door) so there will be room for changes. |
- Adds postopen, prewrite and newsub hooks that allow userland "hook functions" to customize behavior of the database. - Introduces a new `write` event that is emitted on `db.batch()`, `db.put()` and `db.del()`. - Restores support of userland options on batch operations. - Changes nested sublevels to be actually nested. Comes with two low-impact breaking changes, described in `UPGRADING.md`.

Adds postopen, prewrite and newsub hooks that allow userland "hook functions" to customize behavior of the database. See README for details. A quick example:
More generally, this is a move towards "renewed modularity". Our ecosystem is old and many modules no longer work because they had no choice but to monkeypatch database methods, of which the signature has changed since then.
So in addition to hooks, this:
writeevent that is emitted ondb.batch(),db.put()anddb.del()and has richer data: userland options, encoded data, keyEncoding and valueEncoding. Thebatch,putanddelevents are now deprecated and will be removed in a future version. Related to Live streaming values from a level level#222.db.batch(ops, options)to ops, allowing for code likedb.batch(ops, { ttl: 123 })to apply a default userlandttloption to all ops.No breaking changes, yet. Using hooks means opting-in to new behaviors (like the new write event) and disables some old behaviors (like the deprecated events). Later on we can make those the default behavior, regardless of whether hooks are used.
TODO:
batchargument of prewrite hook functionmemory-levelclassic-levelCloses Level/community#44.