fix MR comments

pull/11/head
Timothée Rebours 3 years ago
parent 84c554acee
commit 8c3aac5042
  1. 4
      CHANGELOG.md
  2. 2
      browser-version/lib/storage.react-native.js
  3. 11
      lib/datastore.js
  4. 4
      lib/persistence.js
  5. 92
      test/persistence.async.test.js

@ -12,7 +12,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- The JSDoc is now much more exhaustive. - The JSDoc is now much more exhaustive.
- An auto-generated JSDoc file is generated: [API.md](./API.md). - An auto-generated JSDoc file is generated: [API.md](./API.md).
- Added `Datastore#dropDatabaseAsync` and its callback equivalent. - Added `Datastore#dropDatabaseAsync` and its callback equivalent.
- The Error given when there the `Datastore#corruptAlertThreshold` is reached now has three properties: `dataLength` which is the amount of lines in the database file (excluding empty lines), `corruptItems` which is the amount of corrupted lines, `corruptionRate` which the rate of corruption between 0 and 1. - The Error given when the `Datastore#corruptAlertThreshold` is reached now has three properties: `dataLength` which is the amount of lines in the database file (excluding empty lines), `corruptItems` which is the amount of corrupted lines, `corruptionRate` which the rate of corruption between 0 and 1.
### Changed ### Changed
- The `corruptionAlertThreshold` now doesn't take into account empty lines, and the error message is slightly changed. - The `corruptionAlertThreshold` now doesn't take into account empty lines, and the error message is slightly changed.
@ -44,7 +44,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- `Executor#buffer` & `Executor#queue` do not have the same signatures as before; - `Executor#buffer` & `Executor#queue` do not have the same signatures as before;
- `Executor#push` replaced with `Executor#pushAsync` which is substantially different; - `Executor#push` replaced with `Executor#pushAsync` which is substantially different;
- Storage modules : callback-based functions have been replaced with promise-based functions. - Storage modules : callback-based functions have been replaced with promise-based functions.
- Model module: it has been slightly re-written for clarity, but no changes in its interface was made. - Model module: it has been slightly re-written for clarity, but no changes in its interface were made.
- Typings were updated accordingly. - Typings were updated accordingly.
## Deprecated ## Deprecated

@ -3,7 +3,7 @@
* *
* This version is the React-Native version and uses [@react-native-async-storage/async-storage]{@link https://github.com/react-native-async-storage/async-storage}. * This version is the React-Native version and uses [@react-native-async-storage/async-storage]{@link https://github.com/react-native-async-storage/async-storage}.
* @module storageReactNative * @module storageReactNative
* @see module:storagereact-native * @see module:storageBrowser
* @see module:storage * @see module:storage
* @private * @private
*/ */

@ -312,7 +312,7 @@ class Datastore extends EventEmitter {
* @private * @private
* @type {null|number} * @type {null|number}
*/ */
this.autocompactionIntervalId = null this._autocompactionIntervalId = null
} }
/** /**
@ -342,11 +342,12 @@ class Datastore extends EventEmitter {
*/ */
setAutocompactionInterval (interval) { setAutocompactionInterval (interval) {
const minInterval = 5000 const minInterval = 5000
if (typeof interval !== 'number') throw new Error('Interval must be a number')
const realInterval = Math.max(interval || 0, minInterval) const realInterval = Math.max(interval || 0, minInterval)
this.stopAutocompaction() this.stopAutocompaction()
this.autocompactionIntervalId = setInterval(() => { this._autocompactionIntervalId = setInterval(() => {
this.compactDatafile() this.compactDatafile()
}, realInterval) }, realInterval)
} }
@ -355,9 +356,9 @@ class Datastore extends EventEmitter {
* Stop autocompaction (do nothing if automatic compaction was not running) * Stop autocompaction (do nothing if automatic compaction was not running)
*/ */
stopAutocompaction () { stopAutocompaction () {
if (this.autocompactionIntervalId) { if (this._autocompactionIntervalId) {
clearInterval(this.autocompactionIntervalId) clearInterval(this._autocompactionIntervalId)
this.autocompactionIntervalId = null this._autocompactionIntervalId = null
} }
} }

@ -115,7 +115,7 @@ class Persistence {
* @see Persistence#compactDatafileAsync * @see Persistence#compactDatafileAsync
*/ */
compactDatafile (callback) { compactDatafile (callback) {
deprecate(callback => this.db.compactDatafile(callback), '@seald-io/nedb: calling Datastore#persistence#compactDatafile is deprecated, please use Datastore#compactDatafile, it will be removed in the next major version.')(callback) deprecate(_callback => this.db.compactDatafile(_callback), '@seald-io/nedb: calling Datastore#persistence#compactDatafile is deprecated, please use Datastore#compactDatafile, it will be removed in the next major version.')(callback)
} }
/** /**
@ -123,7 +123,7 @@ class Persistence {
* @deprecated * @deprecated
*/ */
setAutocompactionInterval (interval) { setAutocompactionInterval (interval) {
deprecate(interval => this.db.setAutocompactionInterval(interval), '@seald-io/nedb: calling Datastore#persistence#setAutocompactionInterval is deprecated, please use Datastore#setAutocompactionInterval, it will be removed in the next major version.')(interval) deprecate(_interval => this.db.setAutocompactionInterval(_interval), '@seald-io/nedb: calling Datastore#persistence#setAutocompactionInterval is deprecated, please use Datastore#setAutocompactionInterval, it will be removed in the next major version.')(interval)
} }
/** /**

@ -11,6 +11,7 @@ const storage = require('../lib/storage')
const { execFile, fork } = require('child_process') const { execFile, fork } = require('child_process')
const { promisify } = require('util') const { promisify } = require('util')
const { ensureFileDoesntExistAsync } = require('../lib/storage') const { ensureFileDoesntExistAsync } = require('../lib/storage')
const { once } = require('events')
const Readable = require('stream').Readable const Readable = require('stream').Readable
describe('Persistence async', function () { describe('Persistence async', function () {
@ -337,29 +338,6 @@ describe('Persistence async', function () {
assert.equal(doc2Reloaded, undefined) assert.equal(doc2Reloaded, undefined)
}) })
it('Calling dropDatabase after the datafile was modified loads the new data', async () => {
await d.loadDatabaseAsync()
await d.insertAsync({ a: 1 })
await d.insertAsync({ a: 2 })
const data = d.getAllData()
const doc1 = data.find(doc => doc.a === 1)
const doc2 = data.find(doc => doc.a === 2)
assert.equal(data.length, 2)
assert.equal(doc1.a, 1)
assert.equal(doc2.a, 2)
await fs.writeFile(testDb, '{"a":3,"_id":"aaa"}', 'utf8')
await d.loadDatabaseAsync()
const dataReloaded = d.getAllData()
const doc1Reloaded = dataReloaded.find(function (doc) { return doc.a === 1 })
const doc2Reloaded = dataReloaded.find(function (doc) { return doc.a === 2 })
const doc3Reloaded = dataReloaded.find(function (doc) { return doc.a === 3 })
assert.equal(dataReloaded.length, 1)
assert.equal(doc3Reloaded.a, 3)
assert.equal(doc1Reloaded, undefined)
assert.equal(doc2Reloaded, undefined)
})
it('When treating raw data, refuse to proceed if too much data is corrupt, to avoid data loss', async () => { it('When treating raw data, refuse to proceed if too much data is corrupt, to avoid data loss', async () => {
const corruptTestFilename = 'workspace/corruptTest.db' const corruptTestFilename = 'workspace/corruptTest.db'
const fakeData = '{"_id":"one","hello":"world"}\n' + 'Some corrupt data\n' + '{"_id":"two","hello":"earth"}\n' + '{"_id":"three","hello":"you"}\n' const fakeData = '{"_id":"one","hello":"world"}\n' + 'Some corrupt data\n' + '{"_id":"two","hello":"earth"}\n' + '{"_id":"three","hello":"you"}\n'
@ -369,9 +347,8 @@ describe('Persistence async', function () {
// Default corruptAlertThreshold // Default corruptAlertThreshold
d = new Datastore({ filename: corruptTestFilename }) d = new Datastore({ filename: corruptTestFilename })
await assert.rejects(() => d.loadDatabaseAsync(), err => { await assert.rejects(() => d.loadDatabaseAsync(), err => {
assert.ok(Object.prototype.hasOwnProperty.call(err, 'corruptionRate')) assert.notEqual(err, undefined)
assert.ok(Object.prototype.hasOwnProperty.call(err, 'corruptItems')) assert.notEqual(err, null)
assert.ok(Object.prototype.hasOwnProperty.call(err, 'dataLength'))
assert.equal(err.corruptionRate, 0.25) assert.equal(err.corruptionRate, 0.25)
assert.equal(err.corruptItems, 1) assert.equal(err.corruptItems, 1)
assert.equal(err.dataLength, 4) assert.equal(err.dataLength, 4)
@ -384,9 +361,8 @@ describe('Persistence async', function () {
await fs.writeFile(corruptTestFilename, fakeData, 'utf8') await fs.writeFile(corruptTestFilename, fakeData, 'utf8')
d = new Datastore({ filename: corruptTestFilename, corruptAlertThreshold: 0 }) d = new Datastore({ filename: corruptTestFilename, corruptAlertThreshold: 0 })
await assert.rejects(() => d.loadDatabaseAsync(), err => { await assert.rejects(() => d.loadDatabaseAsync(), err => {
assert.ok(Object.prototype.hasOwnProperty.call(err, 'corruptionRate')) assert.notEqual(err, undefined)
assert.ok(Object.prototype.hasOwnProperty.call(err, 'corruptItems')) assert.notEqual(err, null)
assert.ok(Object.prototype.hasOwnProperty.call(err, 'dataLength'))
assert.equal(err.corruptionRate, 0.25) assert.equal(err.corruptionRate, 0.25)
assert.equal(err.corruptItems, 1) assert.equal(err.corruptItems, 1)
assert.equal(err.dataLength, 4) assert.equal(err.dataLength, 4)
@ -847,40 +823,28 @@ describe('Persistence async', function () {
// Loading it in a separate process that we will crash before finishing the loadDatabase // Loading it in a separate process that we will crash before finishing the loadDatabase
const child = fork('test_lac/loadAndCrash.test', [], { stdio: 'inherit' }) const child = fork('test_lac/loadAndCrash.test', [], { stdio: 'inherit' })
const [code] = await once(child, 'exit')
await Promise.race([ assert.equal(code, 1) // See test_lac/loadAndCrash.test.js
new Promise((resolve, reject) => child.on('error', reject)),
new Promise((resolve, reject) => { assert.equal(await exists('workspace/lac.db'), true)
child.on('exit', async function (code) { assert.equal(await exists('workspace/lac.db~'), true)
try { assert.equal((await fs.readFile('workspace/lac.db', 'utf8')).length, datafileLength)
assert.equal(code, 1) // See test_lac/loadAndCrash.test.js assert.equal((await fs.readFile('workspace/lac.db~', 'utf8')).length, 5000)
assert.equal(await exists('workspace/lac.db'), true) // Reload database without a crash, check that no data was lost and fs state is clean (no temp file)
assert.equal(await exists('workspace/lac.db~'), true) const db = new Datastore({ filename: 'workspace/lac.db' })
assert.equal((await fs.readFile('workspace/lac.db', 'utf8')).length, datafileLength) await db.loadDatabaseAsync()
assert.equal((await fs.readFile('workspace/lac.db~', 'utf8')).length, 5000) assert.equal(await exists('workspace/lac.db'), true)
assert.equal(await exists('workspace/lac.db~'), false)
// Reload database without a crash, check that no data was lost and fs state is clean (no temp file) assert.equal((await fs.readFile('workspace/lac.db', 'utf8')).length, datafileLength)
const db = new Datastore({ filename: 'workspace/lac.db' })
await db.loadDatabaseAsync() const docs = await db.findAsync({})
assert.equal(await exists('workspace/lac.db'), true) assert.equal(docs.length, N)
assert.equal(await exists('workspace/lac.db~'), false) for (i = 0; i < N; i += 1) {
assert.equal((await fs.readFile('workspace/lac.db', 'utf8')).length, datafileLength) docI = docs.find(d => d._id === 'anid_' + i)
assert.notEqual(docI, undefined)
const docs = await db.findAsync({}) assert.deepEqual({ hello: 'world', _id: 'anid_' + i }, docI)
assert.equal(docs.length, N) }
for (i = 0; i < N; i += 1) {
docI = docs.find(d => d._id === 'anid_' + i)
assert.notEqual(docI, undefined)
assert.deepEqual({ hello: 'world', _id: 'anid_' + i }, docI)
}
resolve()
} catch (error) {
reject(error)
}
})
})
])
}) })
// Not run on Windows as there is no clean way to set maximum file descriptors. Not an issue as the code itself is tested. // Not run on Windows as there is no clean way to set maximum file descriptors. Not an issue as the code itself is tested.
@ -946,7 +910,7 @@ describe('Persistence async', function () {
d.setAutocompactionInterval(5000) d.setAutocompactionInterval(5000)
await d.insertAsync({ hello: 'world' }) await d.insertAsync({ hello: 'world' })
await d.dropDatabaseAsync() await d.dropDatabaseAsync()
assert.equal(d.autocompactionIntervalId, null) assert.equal(d._autocompactionIntervalId, null)
assert.equal(d.getAllData().length, 0) assert.equal(d.getAllData().length, 0)
assert.equal(await exists(testDb), false) assert.equal(await exists(testDb), false)
}) })

Loading…
Cancel
Save