@alcalzone/jsonl-db
Advanced tools
Comparing version 2.4.3 to 2.5.0
@@ -57,3 +57,22 @@ export interface JsonlDBOptions<V> { | ||
}; | ||
/** Configure settings related to the lockfile */ | ||
lockfile?: Partial<{ | ||
/** | ||
* Override in which directory the lockfile is created. | ||
* Defaults to the directory in which the DB file is located. | ||
*/ | ||
directory?: string; | ||
/** Duration after which the lock is considered stale. Minimum: 5000, Default: 10000 */ | ||
staleMs?: number; | ||
/** The interval in which the lockfile's `mtime` will be updated. Range: [1000...staleMs/2]. Default: staleMs/2 */ | ||
updateMs?: number; | ||
/** | ||
* How often to retry acquiring a lock before giving up. The retries progressively wait longer with an exponential backoff strategy. | ||
* Range: [0...10]. Default: 0 | ||
*/ | ||
retries?: number; | ||
}>; | ||
/** | ||
* @deprecated Use lockfile.directory instead. | ||
* | ||
* Override in which directory the lockfile is created. | ||
@@ -60,0 +79,0 @@ * Defaults to the directory in which the DB file is located. |
@@ -56,2 +56,3 @@ "use strict"; | ||
constructor(filename, options = {}) { | ||
var _a, _b; | ||
this._db = new Map(); | ||
@@ -67,4 +68,5 @@ this._uncompressedSize = Number.NaN; | ||
this.backupFilename = this.filename + ".bak"; | ||
this.lockfileName = options.lockfileDirectory | ||
? path.join(options.lockfileDirectory, path.basename(this.filename)) | ||
const lockfileDirectory = (_b = (_a = options.lockfile) === null || _a === void 0 ? void 0 : _a.directory) !== null && _b !== void 0 ? _b : options.lockfileDirectory; | ||
this.lockfileName = lockfileDirectory | ||
? path.join(lockfileDirectory, path.basename(this.filename)) | ||
: this.filename; | ||
@@ -107,2 +109,24 @@ this.options = options; | ||
} | ||
if (options.lockfile) { | ||
const { directory, retries, staleMs = 10000, updateMs = staleMs / 2, } = options.lockfile; | ||
if (staleMs < 5000) { | ||
throw new Error("staleMs must be >= 5000"); | ||
} | ||
if (updateMs < 1000) { | ||
throw new Error("updateMs must be >= 1000"); | ||
} | ||
if (updateMs > staleMs / 2) { | ||
throw new Error(`updateMs must be <= ${staleMs / 2}`); | ||
} | ||
if (retries != undefined && retries < 0) { | ||
throw new Error("retries must be >= 0"); | ||
} | ||
if (retries != undefined && retries > 10) { | ||
throw new Error("retries must be <= 10"); | ||
} | ||
if (options.lockfileDirectory != undefined && | ||
directory != undefined) { | ||
throw new Error("lockfileDirectory and lockfile.directory must not both be specified"); | ||
} | ||
} | ||
} | ||
@@ -127,5 +151,12 @@ get size() { | ||
async open() { | ||
var _a; | ||
var _a, _b, _c, _d; | ||
// Open the file for appending and reading | ||
await fs.ensureDir(path.dirname(this.filename)); | ||
let retryOptions; | ||
if ((_a = this.options.lockfile) === null || _a === void 0 ? void 0 : _a.retries) { | ||
retryOptions = { | ||
retries: this.options.lockfile.retries, | ||
factor: 1.25, | ||
}; | ||
} | ||
try { | ||
@@ -140,3 +171,6 @@ await fs.ensureDir(path.dirname(this.lockfileName)); | ||
? 100000 | ||
: /* istanbul ignore next - this is impossible to test */ undefined, | ||
: /* istanbul ignore next - this is impossible to test */ (_b = this | ||
.options.lockfile) === null || _b === void 0 ? void 0 : _b.staleMs, | ||
update: (_c = this.options.lockfile) === null || _c === void 0 ? void 0 : _c.updateMs, | ||
retries: retryOptions, | ||
onCompromised: /* istanbul ignore next */ () => { | ||
@@ -215,3 +249,3 @@ // do nothing | ||
// If the DB should be compressed while opening, do it now | ||
if ((_a = this.options.autoCompress) === null || _a === void 0 ? void 0 : _a.onOpen) | ||
if ((_d = this.options.autoCompress) === null || _d === void 0 ? void 0 : _d.onOpen) | ||
await this.compress(); | ||
@@ -218,0 +252,0 @@ } |
{ | ||
"name": "@alcalzone/jsonl-db", | ||
"version": "2.4.3", | ||
"version": "2.5.0", | ||
"description": "Simple JSONL-based key-value store", | ||
@@ -5,0 +5,0 @@ "main": "./build/index.js", |
@@ -85,10 +85,17 @@ # jsonl-db | ||
### Changing where the lockfile is created | ||
### Lockfile-related options | ||
Normally, the lockfile to avoid concurrent access to the DB file is created right next to the DB file. You can change this, e.g. to put the lockfile into a `tmpfs`: | ||
A lockfile is used to avoid concurrent access to the DB file. Multiple options exist to control where this lockfile is created and how it is accessed: | ||
```ts | ||
const db = new DB("/path/to/file", { lockfileDirectory: "/var/tmp" }); | ||
const db = new DB("/path/to/file", { lockfile: { /* lockfile options */ } }); | ||
``` | ||
If the directory does not exist, it will be created when opening the DB. | ||
| Option | Default | Description | | ||
|-----------------|---------|-------------| | ||
| `directory` | - | Change where the lockfile is created, e.g. to put the lockfile into a `tmpfs`. By default the lockfile is created in the same directory as the DB file. If the directory does not exist, it will be created when opening the DB. | | ||
| `staleMs` | `10000` | Duration after which the lock is considered stale. Minimum: `5000` | | ||
| `updateMs` | `staleMs/2` | The interval in which the lockfile's `mtime` will be updated. Range: `1000 ... staleMs/2` | | ||
| `retries` | `0` | How often to retry acquiring a lock before giving up. The retries progressively wait longer with an exponential backoff strategy. | | ||
### Copying and compressing the database | ||
@@ -146,2 +153,5 @@ | ||
--> | ||
### 2.5.0 (2022-02-13) | ||
* Add the ability to control the lockfile's stale/update timeouts and retrying acquiring a lock | ||
### 2.4.3 (2022-02-09) | ||
@@ -148,0 +158,0 @@ * Errors while automatically compressing the DB are now caught |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
73821
920
245