Comparing version 2.7.11 to 2.8.0
@@ -61,3 +61,3 @@ import { WeakLRUCache, clearKeptObjects } from './native.js'; | ||
return super.get(id, options); | ||
} else { | ||
} else { | ||
value = this.cache.getValue(id); | ||
@@ -79,17 +79,34 @@ if (value !== undefined) { | ||
} | ||
getEntry(id, cacheMode) { | ||
let entry = this.cache.get(id); | ||
if (entry) | ||
return entry; | ||
let value = super.get(id); | ||
getEntry(id, options) { | ||
let entry, value; | ||
if (this.cache.validated) { | ||
entry = this.cache.get(id); | ||
if (entry) { | ||
if (entry.txnId != null) { | ||
value = super.get(id, { ifNotTxnId: entry.txnId, transaction: options && options.transaction }); | ||
if (value === UNMODIFIED) | ||
return entry; | ||
} else // with no txn id we do not validate; this is the state of a cached value after a write before it transacts | ||
return entry; | ||
} else | ||
value = super.get(id, options); | ||
} else if (options && options.transaction) { | ||
return super.getEntry(id, options); | ||
} else { | ||
entry = this.cache.get(id); | ||
if (entry !== undefined) { | ||
return entry; | ||
} | ||
value = super.get(id); | ||
} | ||
if (value === undefined) | ||
return; | ||
if (value && typeof value === 'object' && !cacheMode && typeof id !== 'object') { | ||
if (value && typeof value === 'object' && !options && typeof id !== 'object') { | ||
entry = this.cache.setValue(id, value, this.lastSize >> 10); | ||
} else { | ||
} else | ||
entry = { value }; | ||
} | ||
if (this.useVersions) { | ||
if (this.useVersions) | ||
entry.version = getLastVersion(); | ||
} | ||
if (this.cache.validated) | ||
entry.txnId = getLastTxnId(); | ||
return entry; | ||
@@ -96,0 +113,0 @@ } |
@@ -10,2 +10,3 @@ declare namespace lmdb { | ||
* @param id The key for the entry | ||
* @param options Additional options for the retrieval | ||
**/ | ||
@@ -16,4 +17,5 @@ get(id: K, options?: GetOptions): V | undefined | ||
* @param id The key for the entry | ||
* @param options Additional options for the retrieval | ||
**/ | ||
getEntry(id: K): { | ||
getEntry(id: K, options?: GetOptions): { | ||
value: V | ||
@@ -350,2 +352,3 @@ version?: number | ||
interface GetOptions { | ||
transaction?: Transaction | ||
} | ||
@@ -352,0 +355,0 @@ interface RangeOptions { |
@@ -55,2 +55,3 @@ import { Compression, getAddress, arch, fs, path as pathModule, lmdbError, EventEmitter, MsgpackrEncoder, Env, | ||
options = options || {}; | ||
let noFSAccess = options.noFSAccess; // this can only be configured on open, can't let users change it | ||
let userOptions = options; | ||
@@ -296,2 +297,4 @@ if (!path) { | ||
backup(path, compact) { | ||
if (noFSAccess) | ||
return; | ||
fs.mkdirSync(pathModule.dirname(path), { recursive: true }); | ||
@@ -298,0 +301,0 @@ return new Promise((resolve, reject) => env.copy(path, false, (error) => { |
{ | ||
"name": "lmdb", | ||
"author": "Kris Zyp", | ||
"version": "2.7.11", | ||
"version": "2.8.0", | ||
"description": "Simple, efficient, scalable, high-performance LMDB interface", | ||
@@ -26,2 +26,6 @@ "license": "MIT", | ||
".": { | ||
"types": { | ||
"require": "./index.d.cts", | ||
"import": "./index.d.ts" | ||
}, | ||
"node": { | ||
@@ -31,6 +35,2 @@ "require": "./dist/index.cjs", | ||
}, | ||
"types": { | ||
"require": "./index.d.cts", | ||
"import": "./index.d.ts" | ||
}, | ||
"default": "./index.js" | ||
@@ -68,5 +68,5 @@ } | ||
"prebuild-libc-musl": "ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --tag-libc --napi --platform-packages --target 16.18.0", | ||
"prebuild-libc": "prebuildify-platform-packages --tag-libc --target 19.8.1 || true && prebuildify-platform-packages --tag-libc --target 18.15.0 && prebuildify-platform-packages --tag-libc --target 14.19.1 && prebuildify-platform-packages --platform-packages --tag-libc --target 16.18.0 && ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --napi --platform-packages --tag-libc --target 16.18.0", | ||
"prebuild-macos": "prebuildify-platform-packages --target 18.15.0 && prebuildify-platform-packages --platform-packages --target 16.18.0 && ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --napi --platform-packages --target 16.18.0", | ||
"prebuild-win32": "prebuildify-platform-packages --target 18.15.0 && prebuildify-platform-packages --target 16.18.0 && set ENABLE_V8_FUNCTIONS=false&& prebuildify-platform-packages --napi --platform-packages --target 16.18.0", | ||
"prebuild-libc": "prebuildify-platform-packages --tag-libc --target 20.0.0 || true && prebuildify-platform-packages --tag-libc --target 18.15.0 && prebuildify-platform-packages --platform-packages --tag-libc --target 16.18.0 && ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --napi --platform-packages --tag-libc --target 16.18.0", | ||
"prebuild-macos": "prebuildify-platform-packages --target 20.0.0 && prebuildify-platform-packages --target 18.15.0 && prebuildify-platform-packages --platform-packages --target 16.18.0 && ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --napi --platform-packages --target 16.18.0", | ||
"prebuild-win32": "prebuildify-platform-packages --target 20.0.0 && prebuildify-platform-packages --target 18.15.0 && prebuildify-platform-packages --target 16.18.0 && set ENABLE_V8_FUNCTIONS=false&& prebuildify-platform-packages --napi --platform-packages --target 16.18.0", | ||
"prebuild-libc-arm7": "ENABLE_V8_FUNCTIONS=false prebuildify-platform-packages --napi --platform-packages --tag-libc --target 16.18.0", | ||
@@ -84,7 +84,8 @@ "prebuildify": "prebuildify-platform-packages --napi --target 18.15.0", | ||
"dependencies": { | ||
"msgpackr": "1.8.5", | ||
"node-addon-api": "^4.3.0", | ||
"node-gyp-build-optional-packages": "5.0.6", | ||
"msgpackr": "1.9.1", | ||
"node-addon-api": "^6.1.0", | ||
"node-gyp-build-optional-packages": "5.1.0", | ||
"ordered-binary": "^1.4.0", | ||
"weak-lru-cache": "^1.2.2" | ||
"weak-lru-cache": "^1.2.2", | ||
"yarn": "^1.22.19" | ||
}, | ||
@@ -98,4 +99,4 @@ "devDependencies": { | ||
"mocha": "^10.1.0", | ||
"prebuildify-platform-packages": "5.0.2", | ||
"prebuildify-ci": "^1.0.5", | ||
"prebuildify-platform-packages": "5.0.4", | ||
"rimraf": "^3.0.2", | ||
@@ -113,9 +114,9 @@ "rollup": "^2.61.1", | ||
"optionalDependencies": { | ||
"@lmdb/lmdb-darwin-arm64": "2.7.11", | ||
"@lmdb/lmdb-darwin-x64": "2.7.11", | ||
"@lmdb/lmdb-linux-arm": "2.7.11", | ||
"@lmdb/lmdb-linux-arm64": "2.7.11", | ||
"@lmdb/lmdb-linux-x64": "2.7.11", | ||
"@lmdb/lmdb-win32-x64": "2.7.11" | ||
"@lmdb/lmdb-darwin-arm64": "2.8.0", | ||
"@lmdb/lmdb-darwin-x64": "2.8.0", | ||
"@lmdb/lmdb-linux-arm": "2.8.0", | ||
"@lmdb/lmdb-linux-arm64": "2.8.0", | ||
"@lmdb/lmdb-linux-x64": "2.8.0", | ||
"@lmdb/lmdb-win32-x64": "2.8.0" | ||
} | ||
} |
@@ -359,4 +359,6 @@ import { RangeIterable } from './util/RangeIterable.js'; | ||
let txnAddress; | ||
if (options.transaction) { | ||
txn = options.transaction; | ||
txn = options.transaction | ||
if (txn) { | ||
if (txn.isDone) throw new Error('Can not iterate on range with transaction that is already' + | ||
' done'); | ||
txnAddress = txn.address; | ||
@@ -658,2 +660,3 @@ cursor = null; | ||
} | ||
env.address = 0; | ||
env.close(); | ||
@@ -660,0 +663,0 @@ } else |
@@ -116,7 +116,7 @@ [![license](https://img.shields.io/badge/license-MIT-brightgreen)](LICENSE) | ||
### `db.get(key): any` | ||
This will retrieve the value at the specified key. The `key` must be a JS value/primitive as described above, and the return value will be the stored data (dependent on the encoding), or `undefined` if the entry does not exist. | ||
### `db.get(key, options?): any` | ||
This will retrieve the value at the specified key. The `key` must be a JS value/primitive as described above, and the return value will be the stored data (dependent on the encoding), or `undefined` if the entry does not exist. The `options` argument may be used to specify an explicit read transaction. | ||
### `db.getEntry(key): any` | ||
This will retrieve the the entry at the specified key. The `key` must be a JS value/primitive as described above, and the return value will be the stored entry, or `undefined` if the entry does not exist. An entry is object with a `value` property for the value in the database (as returned by `db.get`), and a `version` property for the version number of the entry in the database (if `useVersions` is enabled for the database). | ||
### `db.getEntry(key, options?): any` | ||
This will retrieve the entry at the specified key. The `key` must be a JS value/primitive as described above, and the return value will be the stored entry, or `undefined` if the entry does not exist. An entry is object with a `value` property for the value in the database (as returned by `db.get`), and a `version` property for the version number of the entry in the database (if `useVersions` is enabled for the database). The `options` argument may be used to specify an explicit read transaction. | ||
@@ -228,3 +228,3 @@ ### `db.put(key, value, version?: number, ifVersion?: number): Promise<boolean>` | ||
#### Snapshots | ||
By default a range iterator will use a database snapshot, using a single read transaction that remains open and gives a consistent view of the database at the time it was started, for the duration of iterating through the range. However, if the iteration will take place over a long period of time, keeping a read transaction open for a long time can interfere with LMDB's free space collection and reuse and increase the database size. If you will be using a long duration iterator, you can specify `snapshot: false` flag in the range options to indicate that it snapshotting is not necessary, and it can reset and renew read transactions while iterating, to allow LMDB to collect any space that was freed during iteration. | ||
By default, a range iterator will use a database snapshot, using a single read transaction that remains open and gives a consistent view of the database at the time it was started, for the duration of iterating through the range. However, if the iteration will take place over a long period of time, keeping a read transaction open for a long time can interfere with LMDB's free space collection and reuse and increase the database size. If you will be using a long duration iterator, you can specify `snapshot: false` flag in the range options to indicate that it snapshotting is not necessary, and it can reset and renew read transactions while iterating, to allow LMDB to collect any space that was freed during iteration. | ||
@@ -310,3 +310,15 @@ ### `db.getValues(key, options?: RangeOptions): Iterable<any>` | ||
### `close(): Promise` | ||
### `db.useReadTransaction(): Transaction` | ||
This allows you to explicitly start a read transaction, which holds a consistent snapshot of the database, and use it for subsequent retrieval operations. This will mark the read transaction as in use until `transaction.done()` is called. For example: | ||
```javascript | ||
let transaction = myDb.useReadTransaction(); | ||
let data = myDb.get('my-key', { transaction }); | ||
await doSomethingElse(); | ||
// the same read transaction is still being used and this will return the same record even if the data has been changed elsewhere: | ||
data = myDb.get('my-key', { transaction }); | ||
transaction.done(); // make sure you mark the transaction as done | ||
``` | ||
It is critical that you mark read transactions as done when you no longer need it or you will exhaust the read transactions that are available. Long-lived read transaction also prevent free space reclamation. This can be used with `get`, `getEntry` and range/query methods. | ||
### `db.close(): Promise` | ||
This will close the current db. This closes the underlying LMDB database, and if this is the root database (opened with `open` as opposed to `db.openDB`), it will close the environment (and child databases will no longer be able to interact with the database). This is asynchronous, waiting for any outstanding transactions to finish before closing the database. | ||
@@ -391,2 +403,4 @@ | ||
By default, opening a database from a root database will inherited the compression settings from the root database. | ||
## Caching | ||
@@ -422,3 +436,3 @@ This library supports caching of entries from databases, and uses a [LRU/LFU (LRFU) and weak-referencing caching mechanism](https://github.com/kriszyp/weak-lru-cache) for highly optimized caching and object tracking. There are several key potential benefits to using caching, including performance, key correlation with object identity, and immediate/synchronous access to saved data. Enabling caching will cache `get`s and `put`s, which can make frequent `get`s much faster. Caching is enabled by providing a truthy value for the `cache` property on the database `options`. | ||
* `name` - This is the name of the database. This defaults to null (which is the root database) when opening the database environment (`open`). When an opening a database within an environment (`openDB`), this is required, if not specified in first parameter. | ||
* `encoding` - Sets the encoding for the database values, which can be `'msgpack'`, `'json'`, `'cbor'`, `'string'`, `'ordered-binary'`or `'binary'`. | ||
* `encoding` - Sets the encoding for the database values, which can be `'msgpack'`, `'json'`, `'cbor'`, `'string'`, `'ordered-binary'`or `'binary'`. Child databases will inherit this from the root database, it is specified. | ||
* `encoder` - Directly set the encoder to use or provide the settings for an encoder. This can be an object with settings to pass to the encoder or can be an object with `encode` and `decode` methods. It can also be an object with an `Encoder` that will be called to create the encoder instance. This allows you explicitly set the encoder with an import: | ||
@@ -425,0 +439,0 @@ |
31
write.js
@@ -37,3 +37,3 @@ import { getAddress, getBufferAddress, write, compress, lmdbError } from './native.js'; | ||
var dynamicBytes; | ||
function allocateInstructionBuffer() { | ||
function allocateInstructionBuffer(lastPosition) { | ||
// Must use a shared buffer on older node in order to use Atomics, and it is also more correct since we are | ||
@@ -43,2 +43,3 @@ // indeed accessing and modifying it from another thread (in C). However, Deno can't handle it for | ||
let buffer = new LocalSharedArrayBuffer(WRITE_BUFFER_SIZE); | ||
let lastBytes = dynamicBytes; | ||
dynamicBytes = new ByteArray(buffer); | ||
@@ -51,2 +52,6 @@ let uint32 = dynamicBytes.uint32 = new Uint32Array(buffer, 0, WRITE_BUFFER_SIZE >> 2); | ||
dynamicBytes.position = 1; // we start at position 1 to save space for writing the txn id before the txn delimiter | ||
if (lastPosition) { | ||
lastBytes.float64[lastPosition + 1] = dynamicBytes.uint32.address + (dynamicBytes.position << 3); | ||
lastBytes.uint32[lastPosition << 1] = 3; // pointer instruction | ||
} | ||
return dynamicBytes; | ||
@@ -236,6 +241,4 @@ } | ||
let lastPosition = position; | ||
targetBytes = allocateInstructionBuffer(); | ||
targetBytes = allocateInstructionBuffer(position); | ||
position = targetBytes.position; | ||
float64[lastPosition + 1] = targetBytes.uint32.address + (position << 3); | ||
uint32[lastPosition << 1] = 3; // pointer instruction | ||
nextUint32 = targetBytes.uint32; | ||
@@ -504,3 +507,8 @@ } else | ||
// so we use the slower atomic operation | ||
return Atomics.or(uint32, flagPosition, newStatus); | ||
try { | ||
return Atomics.or(uint32, flagPosition, newStatus); | ||
} catch(error) { | ||
console.error(error); | ||
return; | ||
} | ||
} | ||
@@ -576,2 +584,7 @@ function afterCommit(txnId) { | ||
} | ||
if (dynamicBytes.position > newBufferThreshold) { | ||
allocateInstructionBuffer(dynamicBytes.position); | ||
nextResolution.flagPosition = dynamicBytes.position << 1; | ||
nextResolution.uint32 = dynamicBytes.uint32; | ||
} | ||
} | ||
@@ -588,3 +601,3 @@ function clearWriteTxn(parentTxn) { | ||
let callback, flags = 15, type = typeof versionOrOptions; | ||
if (type == 'object') { | ||
if (type == 'object' && versionOrOptions) { | ||
if (versionOrOptions.noOverwrite) | ||
@@ -597,3 +610,3 @@ flags |= 0x10; | ||
if (versionOrOptions.ifVersion != undefined) | ||
ifVersion = versionsOrOptions.ifVersion; | ||
ifVersion = versionOrOptions.ifVersion; | ||
versionOrOptions = versionOrOptions.version; | ||
@@ -800,2 +813,4 @@ if (typeof ifVersion == 'function') | ||
this.transactions++; | ||
if (!env.address) | ||
throw new Error('The database has been closed and you can not transact on it'); | ||
env.beginTxn(flags == undefined ? 3 : flags); | ||
@@ -813,3 +828,3 @@ let thisTxn = writeTxn = env.writeTxn = { write: true }; | ||
else { | ||
let hasWrites = env.commitTxn(); | ||
env.commitTxn(); | ||
resetReadTxn(); | ||
@@ -816,0 +831,0 @@ } |
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
2345896
6149
581
12
+ Addedyarn@^1.22.19
+ Added@lmdb/lmdb-darwin-arm64@2.8.0(transitive)
+ Added@lmdb/lmdb-darwin-x64@2.8.0(transitive)
+ Added@lmdb/lmdb-linux-arm@2.8.0(transitive)
+ Added@lmdb/lmdb-linux-arm64@2.8.0(transitive)
+ Added@lmdb/lmdb-linux-x64@2.8.0(transitive)
+ Added@lmdb/lmdb-win32-x64@2.8.0(transitive)
+ Addedmsgpackr@1.9.1(transitive)
+ Addednode-addon-api@6.1.0(transitive)
+ Addednode-gyp-build-optional-packages@5.1.0(transitive)
+ Addedyarn@1.22.22(transitive)
- Removed@lmdb/lmdb-darwin-arm64@2.7.11(transitive)
- Removed@lmdb/lmdb-darwin-x64@2.7.11(transitive)
- Removed@lmdb/lmdb-linux-arm@2.7.11(transitive)
- Removed@lmdb/lmdb-linux-arm64@2.7.11(transitive)
- Removed@lmdb/lmdb-linux-x64@2.7.11(transitive)
- Removed@lmdb/lmdb-win32-x64@2.7.11(transitive)
- Removedmsgpackr@1.8.5(transitive)
- Removednode-addon-api@4.3.0(transitive)
- Removednode-gyp-build-optional-packages@5.0.6(transitive)
Updatedmsgpackr@1.9.1
Updatednode-addon-api@^6.1.0