From 1cd05b4f4167dd70923ba66c3868741ec864c374 Mon Sep 17 00:00:00 2001 From: Vincent Weevers Date: Fri, 12 Jul 2019 07:24:53 +0200 Subject: [PATCH] Update documentation (wip) --- README.md | 90 +++++++++++++++++++++++++--------------------------- UPGRADING.md | 15 +++++++++ package.json | 4 +-- 3 files changed, 59 insertions(+), 50 deletions(-) create mode 100644 UPGRADING.md diff --git a/README.md b/README.md index 1bcbe0a..8f1c3cc 100644 --- a/README.md +++ b/README.md @@ -25,66 +25,62 @@ ## Usage -Augment `levelup` to handle a new `'ttl'` option on `put()` and `batch()` that specifies the number of milliseconds an entry should remain in the data store. After the TTL, the entry will be automatically cleared for you. +**If you are upgrading:** please see [`UPGRADING.md`](UPGRADING.md). -Requires [`levelup`][levelup], [`level`][level] or [`level-hyper`][level-hyper] to be installed separately. +Augment `levelup` to handle a new `ttl` option on `put()` and `batch()` that specifies the number of milliseconds an entry should remain in the data store. After the TTL, the entry will be automatically cleared for you. -**_Note 1: Version 1.0.0 data stores are not backward compatible with previous versions. If you have unexpired entries in a data store managed by pre-1.0.0, don't expect them to expire if you upgrade to 1.0.0+._** _This is due to a level-sublevel change. It is also recommended that you only use level-sublevel 6.0.0+ with level-ttl._ - -**_Note 2: `level-ttl` has partial support for `level-spaces`. It should work fine as long as you don't use the `'defaultTTL'` feature, see below. This is being worked on so we can have full support for `level-spaces` as well._** +Requires [`levelup`][levelup], [`level`][level] or one of its variants like [`level-rocksdb`][level-rocksdb] to be installed separately. ```js -var levelup = require('level') - , ttl = require('level-ttl') +const level = require('level') +const ttl = require('level-ttl') -var db = levelup('/tmp/foo.db') -db = ttl(db) +const db = ttl(level('./db')) -// --------------------------- put() --------------------------- // -// this entry will only stay in the data store for 1 hour -db.put('foo', 'bar', { ttl: 1000 * 60 * 60 }, function (err) { /* .. */ }) +// This entry will only stay in the store for 1 hour +db.put('foo', 'bar', { ttl: 1000 * 60 * 60 }, (err) => { + // .. +}) -// -------------------------- batch() -------------------------- // -// the two 'put' entries will only stay in the data store for 1 hour db.batch([ - { type: 'put', key: 'foo', value: 'bar' } - , { type: 'put', key: 'bam', value: 'boom' } - , { type: 'del', key: 'w00t' } -], { ttl: 1000 * 60 * 60 }, function (err) { /* .. */ }) + // Same for these two entries + { type: 'put', key: 'foo', value: 'bar' }, + { type: 'put', key: 'bam', value: 'boom' }, + { type: 'del', key: 'w00t' } +], { ttl: 1000 * 60 * 5 }, (err) => {}) ``` If you put the same entry twice, you **refresh** the TTL to the _last_ put operation. In this way you can build utilities like [session managers](https://github.com/rvagg/node-level-session/) for your web application where the user's session is refreshed with each visit but expires after a set period of time since their last visit. -Alternatively, for a lower write-footprint you can use the `ttl()` method that is added to your `levelup` instance which can serve to insert or update a ttl for any given key in the database (even if that key doesn't exist but may in the future! Crazy!). +Alternatively, for a lower write-footprint you can use the `ttl()` method that is added to your `levelup` instance which can serve to insert or update a ttl for any given key in the database - even if that key doesn't exist but may in the future! ```js -db.put('foo', 'bar', function (err) { /* .. */ }) -db.ttl('foo', 1000 * 60 * 60, function (err) { /* .. */ }) +db.put('foo', 'bar', (err) => {}) +db.ttl('foo', 1000 * 60 * 60, (err) => {}) ``` -`level-ttl` uses an internal scan every 10 seconds by default, this limits the available resolution of your TTL values, possibly delaying a delete for up to 10 seconds. The resolution can be tuned by passing the `'checkFrequency'` option to the `ttl()` initialiser. +`level-ttl` uses an internal scan every 10 seconds by default, this limits the available resolution of your TTL values, possibly delaying a delete for up to 10 seconds. The resolution can be tuned by passing the `checkFrequency` option to the `ttl()` initialiser. ```js -var db = levelup('/tmp/foo.db') -// scan for deletables every second -db = ttl(db, { checkFrequency: 1000 }) - -/* .. */ +// Scan every second +const db = ttl(level('./db'), { + checkFrequency: 1000 +}) ``` -Of course, a scan takes some resources, particularly on a data store that makes heavy use of TTLs. If you don't require high accuracy for actual deletions then you can increase the `'checkFrequency'`. Note though that a scan only involves invoking a `levelup` ReadStream that returns _only the entries due to expire_, so it doesn't have to manually check through all entries with a TTL. As usual, it's best to not do too much tuning until you have you have something worth tuning! +Of course, a scan takes some resources, particularly on a data store that makes heavy use of TTLs. If you don't require high accuracy for actual deletions then you can increase the `checkFrequency`. Note though that a scan only involves invoking a `levelup` ReadStream that returns _only the entries due to expire_, so it doesn't have to manually check through all entries with a TTL. As usual, it's best to not do too much tuning until you have you have something worth tuning! ### Default TTL -You can set a default ttl value for all your keys by passing the `'defaultTTL'` option to the `ttl()` initialiser. This can be overridden by explicitly setting the ttl value. - -In the following examle `'foo'` will expire in 15 minutes while `'beep'` will expire in one minute. +You can set a default ttl value for all your keys by passing the `defaultTTL` option to the `ttl()` initialiser. This can be overridden per operation. In the following example A will expire in 15 minutes while B will expire in one minute. ```js -var db = levelup('/tmp/foo.db') -db = ttl(db, { defaultTTL: 15 * 60 * 1000 }) -db.put('foo', 'bar', function (err) { /* .. */ }) -db.put('beep', 'boop', { ttl: 60 * 1000 }, function (err) { /* .. */ }) +const db = ttl(level('./db'), { + defaultTTL: 15 * 60 * 1000 +}) + +db.put('A', 'beep', (err) => {}) +db.put('B', 'boop', { ttl: 60 * 1000 }, (err) => {}) ``` ### `opts.sub` @@ -94,14 +90,16 @@ You can provide a custom storage for the meta data by using the `opts.sub` prope A db for the data and a separate to store the meta data: ```js -var level = require('level') - , ttl = require('level-ttl') - , meta = level('./meta') - , db = ttl(level('./db'), { sub: meta }) - , batch = [ - { type: 'put', key: 'foo', value: 'foovalue' } - , { type: 'put', key: 'bar', value: 'barvalue' } - ] +const level = require('level') +const ttl = require('level-ttl') +const meta = level('./meta') + +const db = ttl(level('./db'), { sub: meta }) + +const batch = [ + { type: 'put', key: 'foo', value: 'foo value' }, + { type: 'put', key: 'bar', value: 'bar value' } +] db.batch(batch, { ttl: 100 }, function (err) { db.createReadStream() @@ -117,11 +115,9 @@ db.batch(batch, { ttl: 100 }, function (err) { }) ``` -For more examples on this please check the tests involving `level-sublevel`. - ### Shutting down -`level-ttl` uses a timer to regularly check for expiring entries (don't worry, the whole data store isn't scanned, it's very efficient!). The `db.close()` method is automatically wired to stop the timer but there is also a more explicit db.stop() method that will stop the timer and not pass on to a `close()` underlying `levelup` instance. +`level-ttl` uses a timer to regularly check for expiring entries (don't worry, the whole data store isn't scanned, it's very efficient!). The `db.close()` method is automatically wired to stop the timer but there is also a more explicit `db.stop()` method that will stop the timer and not close the underlying `levelup` instance. ## Contributing @@ -153,4 +149,4 @@ To sustain [`Level`](https://github.com/Level) and its activities, become a back [level]: https://github.com/Level/level -[level-hyper]: https://github.com/Level/level-hyper +[level-rocksdb]: https://github.com/Level/level-rocksdb diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 0000000..9688fb8 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,15 @@ +# Upgrade Guide + +This document describes breaking changes and how to upgrade. ~~For a complete list of changes including minor and patch releases, please refer to the [changelog](CHANGELOG.md)~~. + +## v3 + +Removed use of `level-spaces` internally and dropped support for `options.sublevel`. You can still use `level-spaces` by setting `options.sub`, which should work fine as long as you don't use `options.defaultTTL`. + +## v2 + +Switched to `level-spaces`. + +## v1 + +Version 1.0.0 stores are not backwards compatible with previous versions. If you have unexpired entries in a store managed by < 1.0.0, don't expect them to expire if you upgrade to 1.0.0. This is due to a `level-sublevel` change. It is also recommended that you only use `level-sublevel` >= 6.0.0 with `level-ttl`. diff --git a/package.json b/package.json index 8a60200..13b177b 100644 --- a/package.json +++ b/package.json @@ -2,9 +2,7 @@ "name": "level-ttl", "version": "3.1.1", "description": "Adds a 'ttl' option to levelup for puts and batches", - "authors": [ - "Rod Vagg (https://github.com/rvagg)" - ], + "author": "Rod Vagg (https://github.com/rvagg)", "license": "MIT", "main": "./level-ttl.js", "scripts": {