@lossless.org/nosqldb 10.7.3 → 10.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.smartconfig.json +0 -1
- package/dist_rust/rustdb_linux_amd64 +0 -0
- package/dist_rust/rustdb_linux_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_amd64_musl +0 -0
- package/dist_rust/rustdb_linux_amd64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64 +0 -0
- package/dist_rust/rustdb_linux_arm64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_linux_arm64_musl +0 -0
- package/dist_rust/rustdb_linux_arm64_musl.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_amd64 +0 -0
- package/dist_rust/rustdb_macos_amd64.tsrust-build.json +5 -5
- package/dist_rust/rustdb_macos_arm64 +0 -0
- package/dist_rust/rustdb_macos_arm64.tsrust-build.json +5 -5
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/ts_local/classes.localnosqldb.js +1 -1
- package/dist_ts/ts_nosqldb/classes.storagerehearsal.js +1 -1
- package/dist_ts/ts_nosqldb/resource-fencing.js +1 -1
- package/dist_ts/ts_nosqldb/rust-db-bridge.js +1 -1
- package/dist_ts/ts_nosqldb/server/classes.nosqldbserver.d.ts +2 -0
- package/dist_ts/ts_nosqldb/server/classes.nosqldbserver.js +24 -8
- package/dist_ts/ts_nosqldb/service-types.d.ts +2 -2
- package/dist_ts/ts_nosqldb/stopped-storage.js +1 -1
- package/dist_ts/ts_nosqldb/storage-rehearsal.d.ts +1 -1
- package/dist_ts/ts_nosqldb/storage-rehearsal.js +1 -1
- package/dist_ts/ts_nosqldb/storage-root-alignment.js +1 -1
- package/dist_ts/ts_nosqldb/storage-root-relocation.d.ts +1 -1
- package/dist_ts_debugserver/classes.debugserver.js +1 -1
- package/dist_ts_debugui/nosqldb-debugui.js +1 -1
- package/package.json +6 -6
- package/readme.md +80 -28
- package/third_party_licenses/inventory.json +1 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/ts_nosqldb/server/classes.nosqldbserver.ts +25 -7
package/readme.md
CHANGED
|
@@ -250,11 +250,17 @@ Each entry contains:
|
|
|
250
250
|
|
|
251
251
|
---
|
|
252
252
|
|
|
253
|
+
## 🔢 Document Field Order
|
|
254
|
+
|
|
255
|
+
Like MongoDB, every stored document leads with `_id`. Inserts, upserts, replacements, `findAndModify`, `$out` and `$merge` move a client-supplied `_id` to the front (the Node.js driver appends its generated `_id` after the caller's fields) and generate a missing one there. Every other field keeps its written order: update operators change existing fields in place and append the fields they create, and a replacement keeps its own field order after `_id`. Documents stored with a trailing `_id` by 10.7.3 and earlier keep it until an update, replacement or `$merge` changes them.
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
253
259
|
## ✋ No-Op Write Detection
|
|
254
260
|
|
|
255
261
|
The engine detects document rewrites that change nothing and skips them entirely — no storage write, no WAL append, no index update, and no oplog entry. A skipped rewrite still counts as matched (`matchedCount: 1`) but reports `modifiedCount: 0`.
|
|
256
262
|
|
|
257
|
-
|
|
263
|
+
As in MongoDB, a rewrite is skipped only when the document stays identical: the same fields in the same order with the same values and BSON types, at every depth. Only the position of `_id` is ignored, so a document stored with a trailing `_id` by 10.7.3 and earlier is not rewritten by a write that changes nothing. A replacement or `$set` that only reorders fields is written. Explicit changes to `_updatedAt` are persisted and returned just like changes to any other field. Applications decide when to advance their timestamps.
|
|
258
264
|
|
|
259
265
|
Counters are exposed through `serverStatus`:
|
|
260
266
|
|
|
@@ -390,9 +396,9 @@ semantics. A range is built from `$gt`, `$gte`, `$lt` and `$lte`, and from
|
|
|
390
396
|
`$ne: null` or a `$nin` list holding null, which read only the non-null keys as
|
|
391
397
|
MongoDB's `[MinKey, undefined) ∪ (null, MaxKey]` bounds do: documents without
|
|
392
398
|
the field or with an explicit null are not examined. Ranges are built only on
|
|
393
|
-
complete
|
|
394
|
-
|
|
395
|
-
selected candidate.
|
|
399
|
+
complete indexes whose values all have a scalar order, and on a list field from
|
|
400
|
+
one side of the range only (see **List fields** below); other indexes are not
|
|
401
|
+
narrowed. The full predicate is still checked for every selected candidate.
|
|
396
402
|
|
|
397
403
|
For a query whose filter references only `_id` and whose projection is exactly
|
|
398
404
|
`{ _id: 1 }`, the native primary index can supply the original BSON identity
|
|
@@ -419,6 +425,17 @@ lifetimes remain held through durability. History publication also waits for the
|
|
|
419
425
|
flush. DDL, transactions, index builds, imports and maintenance retain their
|
|
420
426
|
existing independently durable publication paths.
|
|
421
427
|
|
|
428
|
+
The Rust engine registers SIGTERM and SIGINT before reporting readiness. The
|
|
429
|
+
first signal closes request admission, drains admitted commands and native
|
|
430
|
+
workers, and closes storage only after their durable publications finish. An
|
|
431
|
+
admitted transaction commit finishes atomically or aborts; idle transactions
|
|
432
|
+
discard their uncommitted changes. Successful shutdown releases storage-root
|
|
433
|
+
ownership and exits with code 0 even when the parent's management pipe remains
|
|
434
|
+
open. A second shutdown signal, a drain failure, or the overall 40-second
|
|
435
|
+
deadline forces exit with code 70; forced exit does not promise drain completion.
|
|
436
|
+
`NoSqlDbServer.stop()` also succeeds after a confirmed engine exit without
|
|
437
|
+
sending another management request to the dead child.
|
|
438
|
+
|
|
422
439
|
**Storage compatibility:** version 10 adds a 40-byte certified document-ordinal
|
|
423
440
|
record alongside the legacy 8-byte ordinal. It reads existing stores directly;
|
|
424
441
|
startup and reads perform no format rewrite. After version 10 writes certified
|
|
@@ -594,7 +611,8 @@ unique index key wins, and the later writer is told at its own statement.
|
|
|
594
611
|
publish every document.
|
|
595
612
|
- A transaction open for longer than 60 seconds is aborted, as by MongoDB's
|
|
596
613
|
transaction reaper: its staged writes are discarded and its cursors, write
|
|
597
|
-
claims, transaction capacity and database gates are
|
|
614
|
+
claims, transaction capacity and database and collection gates are
|
|
615
|
+
released. The server
|
|
598
616
|
checks idle sessions once a second; a statement still executing when the
|
|
599
617
|
limit passes is not interrupted, and the transaction aborts when that
|
|
600
618
|
statement has finished (MongoDB instead interrupts that statement with
|
|
@@ -630,11 +648,12 @@ reports `TransactionCommitted` (256), commit after abort reports
|
|
|
630
648
|
`$out`/`$merge` reject before transaction admission or mutation.
|
|
631
649
|
|
|
632
650
|
Outside a transaction, `createIndexes` for already installed, identical indexes
|
|
633
|
-
completes without
|
|
651
|
+
completes without waiting for any transaction or publishing a new storage
|
|
634
652
|
position. A repeated physical `create` preserves `NamespaceExists` (48) under
|
|
635
653
|
the same shared admission. Both paths validate current authorization and catalog
|
|
636
|
-
options.
|
|
637
|
-
|
|
654
|
+
options. A new collection or a changed index catalog waits only for the
|
|
655
|
+
transactions that named that collection, and revalidates under its exclusive
|
|
656
|
+
collection gate before any publication (see "Database waits" below).
|
|
638
657
|
|
|
639
658
|
Logical sessions survive socket disconnects. Expiry, `endSessions` and
|
|
640
659
|
`killSessions` drain active work and release cursors and namespace gates.
|
|
@@ -1599,6 +1618,23 @@ only its members. Engines older than this release refuse a storage root that
|
|
|
1599
1618
|
holds a partial index instead of enforcing its uniqueness over every
|
|
1600
1619
|
document.
|
|
1601
1620
|
|
|
1621
|
+
**List fields.** An index on a field that holds lists has an entry per element,
|
|
1622
|
+
as a MongoDB multikey index, and a compound index an entry per combination of
|
|
1623
|
+
its list fields' elements. Equality, `$in` and one-sided ranges on the elements
|
|
1624
|
+
read their bounds, and a document with several entries within them is returned
|
|
1625
|
+
once. A list matches a range bounded on both sides when one element meets the
|
|
1626
|
+
lower bound and one the upper, so such a read takes the side with fewer
|
|
1627
|
+
entries. Equality to a whole list, such as `{ tags: ['a', 'b'] }`, is not
|
|
1628
|
+
answered from element entries, and a list nested in a list stops range reads
|
|
1629
|
+
through the index. An index with element entries returns no order, so a sorted
|
|
1630
|
+
read sorts its matches, and a `hint` naming it is refused. A unique index on a
|
|
1631
|
+
list field is unique per element: a document that shares an element with
|
|
1632
|
+
another is a `DuplicateKey` (11000), while one document may repeat an element.
|
|
1633
|
+
An index whose field already held a list under 10.7.3 or earlier keeps its
|
|
1634
|
+
whole-list entries and uniqueness and is maintained but never selected until it
|
|
1635
|
+
is dropped and created again. Engines up to 10.7.3 refuse an index with element
|
|
1636
|
+
entries instead of maintaining it with whole lists.
|
|
1637
|
+
|
|
1602
1638
|
`find()` and collection `aggregate()` accept `hint` as an index name (including
|
|
1603
1639
|
`_id_`) or an exact ascending/descending key pattern. Key-pattern order matters;
|
|
1604
1640
|
if several indexes share a key pattern, use a name. The selected active scalar
|
|
@@ -1619,8 +1655,8 @@ const count = await collection.countDocuments({ organizationId: 'org-1' }, {
|
|
|
1619
1655
|
|
|
1620
1656
|
Unknown or quarantined indexes, malformed/ambiguous patterns, `$natural`, and
|
|
1621
1657
|
hints on missing collections or views fail explicitly. Forced multikey traversal
|
|
1622
|
-
is unsupported and rejects; unhinted
|
|
1623
|
-
|
|
1658
|
+
is unsupported and rejects; unhinted queries on list fields use element entries
|
|
1659
|
+
as described under **List fields**. Sparse hints intentionally exclude documents absent from that index,
|
|
1624
1660
|
including for empty filters and counts. A hint is never silently replaced by a
|
|
1625
1661
|
collection scan or another index.
|
|
1626
1662
|
|
|
@@ -1775,9 +1811,9 @@ restores a `mongodump` of ordinary collections with its default flags: the
|
|
|
1775
1811
|
documents, validators and supported indexes (unique, compound, sparse,
|
|
1776
1812
|
partial and TTL). It sends this `idIndex` with every `create` and
|
|
1777
1813
|
`createIndexes` with each index's `ns` and `ignoreUnknownIndexOptions: true`,
|
|
1778
|
-
and it builds several collections' indexes in parallel, which
|
|
1779
|
-
|
|
1780
|
-
namespaces (`--nsExclude 'admin.*' --nsExclude 'config.*'`) and create users
|
|
1814
|
+
and it builds several collections' indexes in parallel, which wait for one
|
|
1815
|
+
another instead of failing (see "Database waits" below). Exclude the `admin`
|
|
1816
|
+
and `config` namespaces (`--nsExclude 'admin.*' --nsExclude 'config.*'`) and create users
|
|
1781
1817
|
through NoSQLDB's authentication options. Collections or indexes that use
|
|
1782
1818
|
unsupported features (collation, text, geospatial, hashed or wildcard
|
|
1783
1819
|
indexes, capped or time-series collections) fail the restore with the
|
|
@@ -2095,27 +2131,43 @@ fields:
|
|
|
2095
2131
|
transaction. `getMore` rejects `maxTimeMS` with `BadValue` because NoSQLDB
|
|
2096
2132
|
has no awaitData cursors, and a literal `maxCommitTimeMS` field is rejected
|
|
2097
2133
|
with `InvalidOptions`.
|
|
2098
|
-
- **Database waits.** DDL
|
|
2099
|
-
`collMod`, `dropDatabase`, `renameCollection`,
|
|
2100
|
-
database exclusively; other commands on that
|
|
2101
|
-
wait for a MongoDB
|
|
2134
|
+
- **Database waits.** DDL that drops or reshapes collections (`drop`,
|
|
2135
|
+
`dropIndexes`, `collMod`, `dropDatabase`, `renameCollection`,
|
|
2136
|
+
`$out`/`$merge`) holds its database exclusively; other commands on that
|
|
2137
|
+
database wait for it, as they wait for a MongoDB database lock. Creating a
|
|
2138
|
+
collection or its indexes (`create`, `createIndexes`) holds only that
|
|
2139
|
+
collection exclusively, as MongoDB locks the collection: it waits for the
|
|
2140
|
+
open transactions whose statements targeted that collection (a collection
|
|
2141
|
+
a transaction reads only through `$lookup` or `$unionWith` is not held; the
|
|
2142
|
+
transaction reads its snapshot of it), transaction statements on that
|
|
2143
|
+
collection that arrive after it queue behind it, and everything else
|
|
2144
|
+
proceeds. Commands outside a transaction take no collection
|
|
2145
|
+
gate; writes still queue for the storage writer, which an index build holds
|
|
2146
|
+
until its index is ready. A command outside a
|
|
2102
2147
|
transaction waits first in, first out for as long as it may run: until
|
|
2103
2148
|
`maxTimeMS` (`MaxTimeMSExpired`, code 50), until its client disconnects or
|
|
2104
2149
|
shuts down its sending side (the wait ends with `ClientDisconnect`, code
|
|
2105
2150
|
279, which a client that still reads receives before the connection closes)
|
|
2106
|
-
or until the server shuts down (`InterruptedAtShutdown`, code 91). A
|
|
2107
|
-
command likewise waits for the open transactions on its
|
|
2108
|
-
or abort, and every command on that database that
|
|
2109
|
-
queues behind it, including reads of other collections. An
|
|
2110
|
-
transaction therefore delays DDL and the commands behind it at most
|
|
2111
|
-
the transaction lifetime limit (60 seconds, MongoDB's
|
|
2151
|
+
or until the server shuts down (`InterruptedAtShutdown`, code 91). A
|
|
2152
|
+
database DDL command likewise waits for the open transactions on its
|
|
2153
|
+
database to commit or abort, and every command on that database that
|
|
2154
|
+
arrives after it queues behind it, including reads of other collections. An
|
|
2155
|
+
open transaction therefore delays DDL and the commands behind it at most
|
|
2156
|
+
until the transaction lifetime limit (60 seconds, MongoDB's
|
|
2112
2157
|
`transactionLifetimeLimitSeconds`) aborts it.
|
|
2113
|
-
A transaction statement that needs a further database keeps a
|
|
2114
|
-
five-second limit and then fails with `IllegalOperation` (code 20,
|
|
2158
|
+
A transaction statement that needs a further database or collection keeps a
|
|
2159
|
+
fixed five-second limit and then fails with `IllegalOperation` (code 20,
|
|
2115
2160
|
`EFENCE_BUSY: …`), so a transaction never waits without bound while it
|
|
2116
|
-
holds its databases; like any failed statement, it aborts
|
|
2117
|
-
and releases
|
|
2118
|
-
|
|
2161
|
+
holds its databases and collections; like any failed statement, it aborts
|
|
2162
|
+
the transaction and releases them. One transaction targets at most 4,096
|
|
2163
|
+
distinct collections across all its databases; statements that revisit a
|
|
2164
|
+
collection retain no extra gate. This matches the process-wide collection-lock
|
|
2165
|
+
registry's 4,096-live-identity bound; concurrent transactions and collection
|
|
2166
|
+
DDL share that registry. It bounds process-local locks, not document staging,
|
|
2167
|
+
WAL record size or atomic publication. A statement targeting one more fails
|
|
2168
|
+
with `TooManyRequests`
|
|
2169
|
+
(code 16500) and aborts it. The service operations (export,
|
|
2170
|
+
import, tenant and publication fencing) keep the five-second gate-wait limit and report
|
|
2119
2171
|
`EFENCE_BUSY`.
|
|
2120
2172
|
|
|
2121
2173
|
Callers may therefore rely on a successful NoSQLDB response as a durable,
|
|
@@ -246,7 +246,7 @@
|
|
|
246
246
|
"zmij@1.0.21"
|
|
247
247
|
],
|
|
248
248
|
"files": {
|
|
249
|
-
".smartconfig.json": "
|
|
249
|
+
".smartconfig.json": "a6b17fae7da13c9b5f6eef7049cfd13b497ab7e80739e17446becc0edd5ccefe",
|
|
250
250
|
"license.md": "cfa51b1d8428e453099273832dc2ec1cebdf23d7ba4eda307883158cfc77da2d",
|
|
251
251
|
"rust-toolchain.toml": "8c3afbe90fa0feff766dffd92e6728a569c0a804cf49f1ecd47bf5ac262499b3",
|
|
252
252
|
"rust/Cargo.lock": "aa9659174e579bc943719a5c92ab343d6505a5432e6375254e39abdb1792110a",
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -134,6 +134,7 @@ export class NoSqlDbServer {
|
|
|
134
134
|
private bridgeOwned = false;
|
|
135
135
|
private startInProgress = false;
|
|
136
136
|
private startCompletionPromise: Promise<void> | null = null;
|
|
137
|
+
private stopCompletionPromise: Promise<void> | null = null;
|
|
137
138
|
private isRunning = false;
|
|
138
139
|
private resolvedConnectionUri = '';
|
|
139
140
|
private resolvedPort: number | undefined;
|
|
@@ -157,9 +158,10 @@ export class NoSqlDbServer {
|
|
|
157
158
|
};
|
|
158
159
|
this.bridge = new RustDbBridge({ binaryPath: this.options.binaryPath });
|
|
159
160
|
this.bridge.on('exit', (code: number | null, signal: string | null) => {
|
|
160
|
-
const exitedUnexpectedly = this.isRunning
|
|
161
|
+
const exitedUnexpectedly = this.isRunning
|
|
162
|
+
&& !this.stopCompletionPromise
|
|
163
|
+
&& (code !== 0 || signal !== null);
|
|
161
164
|
this.isRunning = false;
|
|
162
|
-
this.bridgeOwned = false;
|
|
163
165
|
this.resolvedConnectionUri = '';
|
|
164
166
|
this.resolvedPort = undefined;
|
|
165
167
|
if (exitedUnexpectedly) {
|
|
@@ -174,7 +176,7 @@ export class NoSqlDbServer {
|
|
|
174
176
|
async start(optionsArg?: INoSqlDbManagementOperationOptions): Promise<void> {
|
|
175
177
|
validateNoSqlDbManagementOperationOptions(optionsArg);
|
|
176
178
|
optionsArg?.signal?.throwIfAborted();
|
|
177
|
-
if (this.isRunning || this.startInProgress || this.bridgeOwned) {
|
|
179
|
+
if (this.isRunning || this.startInProgress || this.bridgeOwned || this.stopCompletionPromise) {
|
|
178
180
|
throw new Error('Server is already running or still owns a Rust bridge');
|
|
179
181
|
}
|
|
180
182
|
|
|
@@ -333,7 +335,23 @@ export class NoSqlDbServer {
|
|
|
333
335
|
/**
|
|
334
336
|
* Stop the server
|
|
335
337
|
*/
|
|
336
|
-
|
|
338
|
+
stop(): Promise<void> {
|
|
339
|
+
if (this.stopCompletionPromise) {
|
|
340
|
+
return this.stopCompletionPromise;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const stopCompletionPromise = this.stopInternal();
|
|
344
|
+
this.stopCompletionPromise = stopCompletionPromise;
|
|
345
|
+
const releaseStopCompletion = () => {
|
|
346
|
+
if (this.stopCompletionPromise === stopCompletionPromise) {
|
|
347
|
+
this.stopCompletionPromise = null;
|
|
348
|
+
}
|
|
349
|
+
};
|
|
350
|
+
void stopCompletionPromise.then(releaseStopCompletion, releaseStopCompletion);
|
|
351
|
+
return stopCompletionPromise;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
private async stopInternal(): Promise<void> {
|
|
337
355
|
const startCompletionPromise = this.startCompletionPromise;
|
|
338
356
|
if (startCompletionPromise) {
|
|
339
357
|
await startCompletionPromise;
|
|
@@ -344,9 +362,6 @@ export class NoSqlDbServer {
|
|
|
344
362
|
}
|
|
345
363
|
|
|
346
364
|
const requestGracefulStop = this.isRunning && this.bridge.running;
|
|
347
|
-
this.isRunning = false;
|
|
348
|
-
this.resolvedConnectionUri = '';
|
|
349
|
-
this.resolvedPort = undefined;
|
|
350
365
|
if (requestGracefulStop) {
|
|
351
366
|
try {
|
|
352
367
|
await this.bridge.stopDb();
|
|
@@ -357,6 +372,9 @@ export class NoSqlDbServer {
|
|
|
357
372
|
|
|
358
373
|
await this.bridge.terminate();
|
|
359
374
|
this.bridgeOwned = false;
|
|
375
|
+
this.isRunning = false;
|
|
376
|
+
this.resolvedConnectionUri = '';
|
|
377
|
+
this.resolvedPort = undefined;
|
|
360
378
|
}
|
|
361
379
|
|
|
362
380
|
/**
|