add compaction.failed event

feat/compaction-failure-event
Timothée Rebours 11 months ago
parent d4c096b07a
commit 9e36abdd5d
  1. 13
      API.md
  2. 3
      CHANGELOG.md
  3. 14
      lib/datastore.js
  4. 6
      lib/persistence.js
  5. 16
      test/persistence.async.test.js

@ -241,7 +241,7 @@ Will return pointers to matched elements (shallow copies), returning full copies
**Kind**: global class **Kind**: global class
**Extends**: [<code>EventEmitter</code>](http://nodejs.org/api/events.html) **Extends**: [<code>EventEmitter</code>](http://nodejs.org/api/events.html)
**Emits**: <code>Datastore#event:&quot;compaction.done&quot;</code> **Emits**: <code>Datastore#event:&quot;compaction.done&quot;</code>, <code>Datastore#event:&quot;compaction.failed&quot;</code>
* [Datastore](#Datastore) ⇐ [<code>EventEmitter</code>](http://nodejs.org/api/events.html) * [Datastore](#Datastore) ⇐ [<code>EventEmitter</code>](http://nodejs.org/api/events.html)
* [new Datastore(options)](#new_Datastore_new) * [new Datastore(options)](#new_Datastore_new)
@ -282,6 +282,7 @@ Will return pointers to matched elements (shallow copies), returning full copies
* [.remove(query, [options], [cb])](#Datastore+remove) * [.remove(query, [options], [cb])](#Datastore+remove)
* [.removeAsync(query, [options])](#Datastore+removeAsync) ⇒ <code>Promise.&lt;number&gt;</code> * [.removeAsync(query, [options])](#Datastore+removeAsync) ⇒ <code>Promise.&lt;number&gt;</code>
* ["event:compaction.done"](#Datastore+event_compaction.done) * ["event:compaction.done"](#Datastore+event_compaction.done)
* ["event:compaction.failed"](#Datastore+event_compaction.failed)
* _inner_ * _inner_
* [~countCallback](#Datastore..countCallback) : <code>function</code> * [~countCallback](#Datastore..countCallback) : <code>function</code>
* [~findOneCallback](#Datastore..findOneCallback) : <code>function</code> * [~findOneCallback](#Datastore..findOneCallback) : <code>function</code>
@ -743,6 +744,16 @@ if the update did not actually modify them.</p>
<p>Compaction event. Happens when the Datastore's Persistence has been compacted. <p>Compaction event. Happens when the Datastore's Persistence has been compacted.
It happens when calling [compactDatafileAsync](#Datastore+compactDatafileAsync), which is called periodically if you have called It happens when calling [compactDatafileAsync](#Datastore+compactDatafileAsync), which is called periodically if you have called
[setAutocompactionInterval](#Datastore+setAutocompactionInterval).</p> [setAutocompactionInterval](#Datastore+setAutocompactionInterval).</p>
<p>In case of failure, it emits [Datastore#event:"compaction.failed"](Datastore#event:"compaction.failed") instead.</p>
**Kind**: event emitted by [<code>Datastore</code>](#Datastore)
<a name="Datastore+event_compaction.failed"></a>
### "event:compaction.failed"
<p>Compaction event. Happens when the Datastore's Persistence compaction task has failed.
It may happen when calling [compactDatafileAsync](#Datastore+compactDatafileAsync), which is called periodically if you have called
[setAutocompactionInterval](#Datastore+setAutocompactionInterval).</p>
<p>In case of success, it emits [Datastore#event:"compaction.done"](Datastore#event:"compaction.done") instead.</p>
**Kind**: event emitted by [<code>Datastore</code>](#Datastore) **Kind**: event emitted by [<code>Datastore</code>](#Datastore)
<a name="Datastore..countCallback"></a> <a name="Datastore..countCallback"></a>

@ -11,6 +11,9 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
- Explicitly import `buffer` [#34](https://github.com/seald/nedb/pull/34). - Explicitly import `buffer` [#34](https://github.com/seald/nedb/pull/34).
- Fix `Cursor`'s typings [#45](https://github.com/seald/nedb/issues/45) - Fix `Cursor`'s typings [#45](https://github.com/seald/nedb/issues/45)
### Added
- Added a `compaction.failed` event [#28](https://github.com/seald/nedb/issues/28)
## [4.0.3] - 2023-12-13 ## [4.0.3] - 2023-12-13
### Fixed ### Fixed
- Fixed EPERM Exception when datastore is at the root of a disk on Windows [#48](https://github.com/seald/nedb/issues/48) - Fixed EPERM Exception when datastore is at the root of a disk on Windows [#48](https://github.com/seald/nedb/issues/48)

@ -60,10 +60,23 @@ const { isDate, pick, filterIndexNames } = require('./utils.js')
* It happens when calling {@link Datastore#compactDatafileAsync}, which is called periodically if you have called * It happens when calling {@link Datastore#compactDatafileAsync}, which is called periodically if you have called
* {@link Datastore#setAutocompactionInterval}. * {@link Datastore#setAutocompactionInterval}.
* *
* In case of failure, it emits {@link Datastore#event:"compaction.failed"} instead.
*
* @event Datastore#event:"compaction.done" * @event Datastore#event:"compaction.done"
* @type {undefined} * @type {undefined}
*/ */
/**
* Compaction event. Happens when the Datastore's Persistence compaction task has failed.
* It may happen when calling {@link Datastore#compactDatafileAsync}, which is called periodically if you have called
* {@link Datastore#setAutocompactionInterval}.
*
* In case of success, it emits {@link Datastore#event:"compaction.done"} instead.
*
* @event Datastore#event:"compaction.failed"
* @type {Error}
*/
/** /**
* Generic document in NeDB. * Generic document in NeDB.
* It consists of an Object with anything you want inside. * It consists of an Object with anything you want inside.
@ -143,6 +156,7 @@ const { isDate, pick, filterIndexNames } = require('./utils.js')
* @classdesc The `Datastore` class is the main class of NeDB. * @classdesc The `Datastore` class is the main class of NeDB.
* @extends external:EventEmitter * @extends external:EventEmitter
* @emits Datastore#event:"compaction.done" * @emits Datastore#event:"compaction.done"
* @emits Datastore#event:"compaction.failed"
* @typicalname NeDB * @typicalname NeDB
*/ */
class Datastore extends EventEmitter { class Datastore extends EventEmitter {

@ -96,10 +96,10 @@ class Persistence {
* @private * @private
*/ */
async persistCachedDatabaseAsync () { async persistCachedDatabaseAsync () {
try {
const lines = [] const lines = []
if (this.inMemoryOnly) return if (this.inMemoryOnly) return
this.db.getAllData().forEach(doc => { this.db.getAllData().forEach(doc => {
lines.push(this.afterSerialization(model.serialize(doc))) lines.push(this.afterSerialization(model.serialize(doc)))
}) })
@ -117,6 +117,10 @@ class Persistence {
await storage.crashSafeWriteFileLinesAsync(this.filename, lines, this.modes) await storage.crashSafeWriteFileLinesAsync(this.filename, lines, this.modes)
this.db.emit('compaction.done') this.db.emit('compaction.done')
} catch (error) {
this.db.emit('compaction.failed', error)
throw error
}
} }
/** /**

@ -368,6 +368,7 @@ describe('Persistence async', function () {
}) })
it('Can listen to compaction events', async () => { it('Can listen to compaction events', async () => {
d.insertAsync({ a: 2 })
const compacted = new Promise(resolve => { const compacted = new Promise(resolve => {
d.once('compaction.done', function () { d.once('compaction.done', function () {
resolve() resolve()
@ -375,6 +376,21 @@ describe('Persistence async', function () {
}) })
await d.compactDatafileAsync() await d.compactDatafileAsync()
await compacted // should already be resolved when the function returns, but still awaiting for it await compacted // should already be resolved when the function returns, but still awaiting for it
const failure = new Promise(resolve => {
d.once('compaction.failed', function (error) {
resolve(error)
})
})
const afterSerializationOriginal = d.persistence.afterSerialization
d.persistence.afterSerialization = () => { throw new Error('synthetic error') }
await d.compactDatafileAsync().then(() => { throw new Error('should have failed') }, error => {
if (!error || !(error instanceof Error) || error.message !== 'synthetic error') throw error
})
const error = await failure
if (!error || !(error instanceof Error) || error.message !== 'synthetic error') throw error
d.persistence.afterSerialization = afterSerializationOriginal
}) })
it('setAutocompaction fails gracefully when passed a NaN', async () => { it('setAutocompaction fails gracefully when passed a NaN', async () => {

Loading…
Cancel
Save