@lossless.org/client 1.7.0 → 1.9.0
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/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/nosqldb/classes.atomicdelete.d.ts +1 -0
- package/dist_ts/nosqldb/classes.atomicdelete.js +10 -7
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.d.ts +2 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.js +9 -5
- package/dist_ts/nosqldb/classes.atomicupdate.d.ts +2 -0
- package/dist_ts/nosqldb/classes.atomicupdate.js +13 -8
- package/dist_ts/nosqldb/classes.collection.d.ts +13 -4
- package/dist_ts/nosqldb/classes.collection.js +57 -64
- package/dist_ts/nosqldb/classes.db.d.ts +1 -1
- package/dist_ts/nosqldb/classes.doc.d.ts +60 -3
- package/dist_ts/nosqldb/classes.doc.js +68 -26
- package/dist_ts/nosqldb/classes.exactpersistence.d.ts +36 -7
- package/dist_ts/nosqldb/classes.exactpersistence.js +92 -81
- package/dist_ts/nosqldb/classes.operationdeadline.d.ts +61 -0
- package/dist_ts/nosqldb/classes.operationdeadline.js +149 -0
- package/dist_ts/nosqldb/classes.persistence.d.ts +16 -1
- package/dist_ts/nosqldb/classes.persistence.js +20 -1
- package/dist_ts/nosqldb/classes.session.d.ts +73 -2
- package/dist_ts/nosqldb/classes.session.js +164 -38
- package/dist_ts/objectstorage/classes.bucket.d.ts +8 -3
- package/dist_ts/objectstorage/classes.bucket.js +83 -131
- package/dist_ts/objectstorage/classes.directory.js +17 -28
- package/dist_ts/objectstorage/classes.smartbucket.d.ts +13 -6
- package/dist_ts/objectstorage/classes.smartbucket.js +18 -12
- package/dist_ts/objectstorage/classes.watcher.js +1 -2
- package/dist_ts/objectstorage/interfaces.d.ts +8 -0
- package/dist_ts/objectstorage/internal.bucketrequests.d.ts +14 -0
- package/dist_ts/objectstorage/internal.bucketrequests.js +53 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.d.ts +12 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.js +46 -17
- package/package.json +2 -2
- package/readme.md +14 -7
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/nosqldb/classes.atomicdelete.ts +10 -6
- package/ts/nosqldb/classes.atomicfindoneandupdate.ts +10 -4
- package/ts/nosqldb/classes.atomicupdate.ts +14 -7
- package/ts/nosqldb/classes.collection.ts +82 -73
- package/ts/nosqldb/classes.db.ts +1 -1
- package/ts/nosqldb/classes.doc.ts +162 -33
- package/ts/nosqldb/classes.exactpersistence.ts +131 -93
- package/ts/nosqldb/classes.operationdeadline.ts +179 -0
- package/ts/nosqldb/classes.persistence.ts +36 -1
- package/ts/nosqldb/classes.session.ts +221 -39
- package/ts/objectstorage/classes.bucket.ts +111 -158
- package/ts/objectstorage/classes.directory.ts +18 -27
- package/ts/objectstorage/classes.smartbucket.ts +21 -11
- package/ts/objectstorage/classes.watcher.ts +0 -1
- package/ts/objectstorage/interfaces.ts +9 -0
- package/ts/objectstorage/internal.bucketrequests.ts +70 -0
- package/ts/objectstorage/internal.exactupload.capability.ts +105 -24
package/readme.md
CHANGED
|
@@ -102,18 +102,23 @@ Family imports preserve the established SmartData and SmartBucket names and cons
|
|
|
102
102
|
| Migration-owned indexes | `toleratedIndexNames` on the model — named undeclared indexes are observed, never created, dropped or verified, and no longer make the topology divergent |
|
|
103
103
|
| Partial index filters in inspection | `inspectNamespace()`, `inspectCollectionTopology()` and `getIndexInfo()` report a partial index's `partialFilterExpression` exactly as the backend lists it, as a frozen snapshot present only on a partial index |
|
|
104
104
|
| Key-value store readiness | `EasyStore.ensureInitialized()` — installs the store's declared index at startup, outside any transaction window, so a first `readKey()`/`writeKey()` needs no index DDL |
|
|
105
|
+
| Client deadlines | `timeoutMS` (1..120000) on every ordinary model read and write, instance `save()`/`saveIf()`/`delete()` included, on every exact call, and `session.withTransaction(callback, { timeoutMS })` for a whole transaction, retries and commit included; expiry rejects with `SmartdataPersistenceError` code `timeout`, and an exact write interrupted in flight with `ambiguous_write` |
|
|
106
|
+
| Cancellation | `signal` on every exact call, `atomicDeleteMany()` and `session.withTransaction(callback, { signal })`, which interrupts the session's operation in flight, rolls the attempt back and never commits after an abort |
|
|
105
107
|
|
|
106
108
|
`docs/source/smartdata/readme.md` documents each one with its refusals.
|
|
107
109
|
|
|
108
110
|
| `@lossless.org/client/objectstorage` addition | API |
|
|
109
111
|
| --- | --- |
|
|
110
112
|
| Listing with size and ETag | `bucket.listObjectEntriesPage({ prefix?, limit, startAfter?, signal? })` — one keyset page of `{ key, size, etag, lastModified? }`; `bucket.listAllObjectEntries(prefix?, { pageSize?, signal? })` iterates every page |
|
|
113
|
+
| Bucket lookup for bucket-scoped credentials | `smartBucket.getBucketByName(name, { signal? })` and `smartBucket.bucketExists(name, { signal? })` send one HeadBucket; `createBucket(name, { signal? })` and `removeBucket(name, { signal? })` take the same options |
|
|
114
|
+
|
|
115
|
+
A bucket lookup sends one HeadBucket for the named bucket, never ListBuckets, so a credential scoped to its bucket can open it without the account-wide list permission, and a lookup does not depend on which buckets a listing returns. A missing bucket (404) keeps its answer: `getBucketByName()` rejects with `Bucket '<name>' not found.` and `bucketExists()` resolves `false`. A bucket the credentials may not access (403) rejects both with an error that names the denial and keeps the provider error as `cause`; S3 does not say whether such a bucket exists. Any other provider failure is rethrown unchanged. `signal` aborts the in-flight request and rejects with the signal's reason. Lookups, creations and removals run as lifecycle-managed operations: `SmartBucket.close()` aborts and awaits them, and the storage client cannot be replaced while one is active.
|
|
111
116
|
|
|
112
117
|
`listObjectEntriesPage()` pages exactly like `listObjectKeysPage()`: `limit` is 1 to 1000, `startAfter` must be a non-empty key under the prefix, entries arrive in strict UTF-8 byte order after it, and `nextStartAfter` is present only while the provider reports more. Keyset pages stay valid when earlier keys are deleted between requests. Every field comes from the one ListObjectsV2 response, so no HEAD is sent per object. `size` is the listed `Size`, the byte length HEAD reports as `ContentLength`. `etag` is the listed `ETag` with its surrounding double quotes removed; HEAD returns the same entity tag, quoted. An entity tag identifies an object version and is not a content digest: AWS S3 derives it from the content MD5 only for single-part uploads without SSE-KMS or SSE-C, and a multipart tag ends in `-<parts>`. `lastModified` is present when the provider sends `LastModified`. Both values describe the object when the page was listed. A page with a missing or non-integer size, a missing or malformed ETag, or any key-page violation is refused rather than returned partially. `signal` aborts the in-flight request and rejects with the signal's reason; the iterator issues one request per page and none while the caller holds an entry, so breaking out ends the listing.
|
|
113
118
|
|
|
114
119
|
### Document APIs that need a MongoDB backend
|
|
115
120
|
|
|
116
|
-
The document model runs on both NoSQLDB and MongoDB, but
|
|
121
|
+
The document model runs on both NoSQLDB and MongoDB, but several APIs do not mean the same thing on both. The NoSQLDB engine is qualified at 8.0.2 and 10.7.0 (see [Verification](#verification)); the two releases part on the grouped-totals and guarded-`$expr` rows below — 10.7.0 groups composite keys exactly and evaluates the guard, 8.0.2 does neither — on whether a migration can create a partial index or a collection validator at all, and on when a transaction learns of a write conflict.
|
|
117
122
|
|
|
118
123
|
`init()` asks the connected engine what it is with one `buildInfo` command and records the answer on the database as `engineIdentity` (`{ product, version }`). NoSQLDB answers with its own `nosqldb` identity document from 10.3.0 onward; a MongoDB server answers `buildInfo` without one; an engine that refuses the command — NoSQLDB 8.0.2 answers `CommandNotFound` — stays `{ product: 'unknown', version: null }`. The identity is what states `capabilities` on a plain `SmartdataDb`, and an unidentified engine states none at all, so every capability-gated call refuses. `NoSqlConnection` keeps stating the capabilities of its declared backend from construction on.
|
|
119
124
|
|
|
@@ -121,12 +126,14 @@ The document model runs on both NoSQLDB and MongoDB, but four APIs do not mean t
|
|
|
121
126
|
| --- | --- | --- |
|
|
122
127
|
| `getGroupedTotals()` / `getGroupedTotalsPage()` with one `groupBy` field | exact, including `sums` | exact |
|
|
123
128
|
| the same with **two** `groupBy` fields | exact, `sums` included, on an engine that identifies itself as NoSQLDB 10.5.0 or newer: that release evaluates the composite group key per document. Below it the call is refused with `unsupported_operation` naming both fields and the single-field form, because the engine leaves the composite group key unresolved and answers with a single row whose group values are the literal field paths (`'$owner'`) and whose count is the whole filtered collection; the refusal is the guard against that wrong number, not a fix for it | exact |
|
|
124
|
-
| guarded `$expr` atomic filters (`$add`, `$lte`, `$ifNull`) | exact on 10.6.0: the engine evaluates the client's fail-closed compilation (`$cond`, `$let`, `$isNumber`, `$type`), so the guard admits within the limit, refuses beyond it and never matches a stored value that is not a finite number. 8.0.2 rejects the compilation with `invalid argument: $cond` and leaves the document untouched | exact |
|
|
129
|
+
| guarded `$expr` atomic filters (`$add`, `$lte`, `$ifNull`) | exact on 10.6.0 and newer: the engine evaluates the client's fail-closed compilation (`$cond`, `$let`, `$isNumber`, `$type`), so the guard admits within the limit, refuses beyond it and never matches a stored value that is not a finite number. 8.0.2 rejects the compilation with `invalid argument: $cond` and leaves the document untouched | exact |
|
|
125
130
|
| `watch()` change streams | unsupported. `NoSqlConnection` refuses with `unsupported_capability`, and so does a plain `SmartdataDb` whose engine identified itself; against an engine that answers no identity the refusal instead arrives from the engine as `CommandNotFound` once the change stream is read | supported on replica sets |
|
|
126
|
-
| model-declared partial indexes (`partialFilterExpression`) | not expressible: the index-option type rejects it and the runtime refuses it with `invalid_configuration`. A client decision, not an engine limit on every release — 10.6.0
|
|
131
|
+
| model-declared partial indexes (`partialFilterExpression`) | not expressible: the index-option type rejects it and the runtime refuses it with `invalid_configuration`. A client decision, not an engine limit on every release — 10.6.0 and newer create partial indexes, 8.0.2 refuses the option with `InvalidOptions` (72) — because one model declaration has to hold on every qualified backend. A migration may create one on 10.7.0; `toleratedIndexNames` accepts it and inspection reports its filter | not expressible, but a migration may own one; inspection reports its filter |
|
|
132
|
+
| collection validators (`validator`, `validationLevel`, `validationAction`) | no client API; a migration owns a validator through the driver. 10.7.0 creates the collection, lists the options exactly as given and enforces them on every model write: a violating `insert()` or `atomicUpdate()` rejects with the engine's `DocumentValidationFailure` (121) and its `errInfo`, which the client passes through unchanged rather than mapping to a `SmartdataPersistenceError` code, and stores nothing. Models initialize on a validated collection like on any other. 8.0.2 refuses the option with `InvalidOptions` (72) and creates no collection, so a validator is never silently dropped | enforced; not exercised by the client's MongoDB suite |
|
|
133
|
+
| write conflicts between transactions, and writes outside a transaction to a document a transaction holds | 10.7.0 (since 10.6.1) detects a conflict at the statement, as MongoDB does: the first writer wins, and the later transaction's statement rejects with the engine's `WriteConflict` (112) labelled `TransientTransactionError`, which the client passes through so `session.withTransaction()` re-runs that callback. A write outside a transaction waits until the transaction holding its document ends, then applies on top; the wait is bounded by the write's own `timeoutMS` and by the engine's fixed 60-second transaction lifetime, after which a waiting writer aborts the holder. Awaiting such a write inside the holding transaction's callback therefore stalls that transaction until one of the two expires. 8.0.2 detects the conflict at commit: the first transaction to commit wins, a write outside a transaction applies at once, and the transaction that wrote first re-runs. Both writes land on either engine; a callback must be safe to re-run and must not swallow the statement error | first writer wins at the statement and outside writes wait, MongoDB's documented rule; not exercised by the client's MongoDB suite |
|
|
127
134
|
| aggregation-pipeline (array) updates | refused by the client with `invalid_argument` before any backend is contacted. A client-owned refusal, not an engine limit: both qualified engines apply a pipeline update themselves | same client refusal |
|
|
128
135
|
|
|
129
|
-
`test/nosqldb/smartdb/test.engine-capability-boundary.node.ts` asserts the identity, grouped-totals, guarded-`$expr`, partial-index and pipeline-update rows against both qualified engines, so a boundary that moves shows up as a failing suite rather than as a changed number in a consumer. The two halves of the grouped-totals
|
|
136
|
+
`test/nosqldb/smartdb/test.engine-capability-boundary.node.ts` asserts the identity, grouped-totals, guarded-`$expr`, partial-index, collection-validator, write-conflict and pipeline-update rows against both qualified engines, so a boundary that moves shows up as a failing suite rather than as a changed number in a consumer. The two halves of the grouped-totals, guarded-`$expr` and write-conflict rows are separate tests, each bound to the engine that answers it, and the engine's own composite-key answer stays under assertion through the raw `aggregateGroupedTotals()` boundary — one literal row on 8.0.2, the two exact pairs on 10.7.0. The same boundary pins the rest of the engine's `$group` stage: a non-document accumulator is refused with `TypeMismatch` (14) on 10.7.0 while 8.0.2 answers it, and a `$cond` inside a composite key is evaluated per document on 10.7.0 while 8.0.2 answers its single literal row. It also pins whether a migration can create a partial index — 10.7.0 creates it and lists the filter, 8.0.2 refuses with 72 — and a collection validator — 10.7.0 creates and enforces it against model inserts and updates, 8.0.2 refuses with 72 — and which writer a conflict sends back: on 10.7.0 the later transaction fails at its statement and re-runs while a write outside a transaction waits for the holder's commit, on 8.0.2 the later transaction commits first and the holder re-runs. The `watch()` row is the contract refusal `ts/nosqldb/classes.collection.ts` states; the engine suite opens no change stream.
|
|
130
137
|
|
|
131
138
|
## Relational SQL
|
|
132
139
|
|
|
@@ -171,7 +178,7 @@ New SQL methods accept `signal` and a total `timeoutMs` (30 seconds by default,
|
|
|
171
178
|
|
|
172
179
|
`LosslessClientError` provides a safe outer message, a code, optional `backendCode`, `retryability`, `outcome` and acknowledged-row evidence. `cause` preserves the original error and can contain statement values; do not log it indiscriminately. The taxonomy includes invalid arguments, unsupported capability, a missing optional driver, authentication, conflict, timeout, cancellation, result limits, backend failure, partial writes and unknown write outcomes. There are no automatic write retries. A transient hint never establishes that retrying an ambiguous write is safe.
|
|
173
180
|
|
|
174
|
-
Migrated document and object APIs retain their existing typed errors and exact-operation evidence. Their established per-operation timeout/ownership contracts continue to apply. `capabilities` distinguishes `available`, `unsupported` and `unknown`; MongoDB transaction/change-stream availability still depends on deployment topology. NoSQLDB change streams are explicitly unsupported. `capabilities.compositeGrouping` is the one member with its own vocabulary — `exact` or `unsupported` — and states whether two-field grouped totals are evaluated exactly; MongoDB and NoSQLDB 10.5.0 and newer are `exact`, every earlier or unidentified engine and every relational or object connection is `unsupported`. On a plain `SmartdataDb` the whole statement is `undefined` until `init()` identifies the engine, and an absent statement means "not available". S3 exact-operation capability tests remain explicit and require owned disposable resources.
|
|
181
|
+
Migrated document and object APIs retain their existing typed errors and exact-operation evidence. Their established per-operation timeout/ownership contracts continue to apply. Ordinary document calls and every exact call take a client-side `timeoutMS` that the driver enforces from server selection to the last reply, and `session.withTransaction(callback, { timeoutMS })` bounds a whole transaction; an expired deadline rejects with `SmartdataPersistenceError` code `timeout`, and a write or commit that expired has an unknown outcome, which an exact write reports as `ambiguous_write`. The same exact calls, `atomicDeleteMany()` and `withTransaction()` take an `AbortSignal`; an aborted transaction is rolled back and never committed, while a commit already in flight runs to its own outcome. `docs/source/smartdata/readme.md` describes both, including the two driver cleanups that run on a fresh deadline of the same length after the deadline expired — the closing abort of a transaction whose callback stalled, and the `killCursors` after a stalled `getMore` of a read that needs more than one batch — so either settles within about twice `timeoutMS`. `capabilities` distinguishes `available`, `unsupported` and `unknown`; MongoDB transaction/change-stream availability still depends on deployment topology. NoSQLDB change streams are explicitly unsupported. `capabilities.compositeGrouping` is the one member with its own vocabulary — `exact` or `unsupported` — and states whether two-field grouped totals are evaluated exactly; MongoDB and NoSQLDB 10.5.0 and newer are `exact`, every earlier or unidentified engine and every relational or object connection is `unsupported`. On a plain `SmartdataDb` the whole statement is `undefined` until `init()` identifies the engine, and an absent statement means "not available". S3 exact-operation capability tests remain explicit and require owned disposable resources.
|
|
175
182
|
|
|
176
183
|
## Migrating existing applications
|
|
177
184
|
|
|
@@ -206,14 +213,14 @@ Qualified engines:
|
|
|
206
213
|
|
|
207
214
|
| Component | Qualified versions |
|
|
208
215
|
| --- | --- |
|
|
209
|
-
| NoSQLDB engine | **8.0.2 and 10.
|
|
216
|
+
| NoSQLDB engine | **8.0.2 and 10.7.0** — the same `test/nosqldb/smartdb/` suite runs against both, through the single engine seam in `test/nosqldb/helpers/smartdb.ts`; `NOSQLDB_ENGINE=qualified` selects 10.7.0 |
|
|
210
217
|
| MongoDB | 8.0.26 replica sets |
|
|
211
218
|
| ObjectStorage | 10.3.1 |
|
|
212
219
|
| SQLDB | 0.2.3 |
|
|
213
220
|
| MariaDB | 11.8 |
|
|
214
221
|
| ClickHouse | 25.8 |
|
|
215
222
|
|
|
216
|
-
Both engine versions run the whole document suite. They part on asserted boundaries — 10.
|
|
223
|
+
Both engine versions run the whole document suite. They part on asserted boundaries — 10.7.0 groups composite keys exactly and answers two-field grouped totals, evaluates guarded `$expr` filters, creates migration-owned partial indexes and collection validators and reports a transaction write conflict at the statement, 8.0.2 does none of these, reports the conflict at commit, and the client refuses the two-field form there — which [Document APIs that need a MongoDB backend](#document-apis-that-need-a-mongodb-backend) states row by row. Text search, the Lucene adapter and the broad read-filter surface are exercised against MongoDB only. `pnpm run test:minio` uses a digest-pinned MinIO image: `sha256:14cea493d9a34af32f524e538b8346cf79f3321eff8e708c1e2960462bd8936e`. That MinIO version enforces the tested conditional uploads but does not enforce conditional deletion; its exact-purge capability is correctly unavailable. ObjectStorage passes both live probes. AWS S3 has not been qualified against a live account in this migration; no universal S3 exact-operation guarantee is inferred from the SDK.
|
|
217
224
|
|
|
218
225
|
## License and Legal Information
|
|
219
226
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -27,14 +27,15 @@ export const executeAtomicDelete = async <T>(
|
|
|
27
27
|
ordinaryWrite: true,
|
|
28
28
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
29
29
|
collectionName: collectionArg.collectionName,
|
|
30
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
30
31
|
},
|
|
31
|
-
async (rawSessionArg) => {
|
|
32
|
-
await collectionArg.init();
|
|
32
|
+
async (rawSessionArg, deadlineArg) => {
|
|
33
|
+
await deadlineArg.join(collectionArg.init());
|
|
33
34
|
return collectionArg.mongoDbCollection.deleteOne(
|
|
34
35
|
filterArg,
|
|
35
36
|
{
|
|
36
37
|
session: rawSessionArg,
|
|
37
|
-
|
|
38
|
+
...deadlineArg.commandOptions(),
|
|
38
39
|
},
|
|
39
40
|
);
|
|
40
41
|
},
|
|
@@ -55,6 +56,7 @@ export const executeAtomicDeleteMany = async <T>(
|
|
|
55
56
|
optsArg?: {
|
|
56
57
|
session?: TSmartdataOrdinarySession;
|
|
57
58
|
timeoutMS?: number;
|
|
59
|
+
signal?: AbortSignal;
|
|
58
60
|
},
|
|
59
61
|
): Promise<plugins.mongodb.DeleteResult> => {
|
|
60
62
|
return runWithOrdinarySmartdataSession(
|
|
@@ -64,14 +66,16 @@ export const executeAtomicDeleteMany = async <T>(
|
|
|
64
66
|
ordinaryWrite: true,
|
|
65
67
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
66
68
|
collectionName: collectionArg.collectionName,
|
|
69
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
70
|
+
signal: optsArg?.signal,
|
|
67
71
|
},
|
|
68
|
-
async (rawSessionArg) => {
|
|
69
|
-
await collectionArg.init();
|
|
72
|
+
async (rawSessionArg, deadlineArg) => {
|
|
73
|
+
await deadlineArg.join(collectionArg.init());
|
|
70
74
|
return collectionArg.mongoDbCollection.deleteMany(
|
|
71
75
|
filterArg,
|
|
72
76
|
{
|
|
73
77
|
session: rawSessionArg,
|
|
74
|
-
|
|
78
|
+
...deadlineArg.commandOptions(),
|
|
75
79
|
},
|
|
76
80
|
);
|
|
77
81
|
},
|
|
@@ -95,6 +95,7 @@ export const executeAtomicFindOneAndUpdate = async <T>(
|
|
|
95
95
|
upsert: boolean;
|
|
96
96
|
sort?: Record<string, 1 | -1>;
|
|
97
97
|
session?: TSmartdataOrdinarySession;
|
|
98
|
+
timeoutMS?: number;
|
|
98
99
|
},
|
|
99
100
|
): Promise<TAtomicFindOneAndUpdateExecutionResult> => {
|
|
100
101
|
const policy = collectionArg.getBoundModelSchema()?.ordinaryPersistence;
|
|
@@ -109,13 +110,14 @@ export const executeAtomicFindOneAndUpdate = async <T>(
|
|
|
109
110
|
ordinaryWrite: true,
|
|
110
111
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
111
112
|
collectionName: collectionArg.collectionName,
|
|
113
|
+
timeoutMS: optionsArg.timeoutMS,
|
|
112
114
|
},
|
|
113
|
-
async (rawSessionArg) => {
|
|
115
|
+
async (rawSessionArg, deadlineArg) => {
|
|
114
116
|
if (policy && !rawSessionArg?.inTransaction()) {
|
|
115
117
|
throw new SmartdataPersistenceError('unsupported_operation',
|
|
116
118
|
'Validated ordinary updates require an active owned transaction.');
|
|
117
119
|
}
|
|
118
|
-
await collectionArg.init();
|
|
120
|
+
await deadlineArg.join(collectionArg.init());
|
|
119
121
|
try {
|
|
120
122
|
const result = await collectionArg.mongoDbCollection.findOneAndUpdate(
|
|
121
123
|
filterArg,
|
|
@@ -126,6 +128,7 @@ export const executeAtomicFindOneAndUpdate = async <T>(
|
|
|
126
128
|
upsert: optionsArg.upsert,
|
|
127
129
|
...(optionsArg.sort ? { sort: optionsArg.sort } : {}),
|
|
128
130
|
session: rawSessionArg,
|
|
131
|
+
...deadlineArg.commandOptions(),
|
|
129
132
|
},
|
|
130
133
|
);
|
|
131
134
|
try {
|
|
@@ -170,6 +173,7 @@ export const executeAtomicFindOneAndReplace = async <T>(
|
|
|
170
173
|
optionsArg: {
|
|
171
174
|
returnDocument: 'before' | 'after';
|
|
172
175
|
session?: TSmartdataOrdinarySession;
|
|
176
|
+
timeoutMS?: number;
|
|
173
177
|
},
|
|
174
178
|
): Promise<TAtomicFindOneAndReplaceExecutionResult> => {
|
|
175
179
|
if (collectionArg.getBoundModelSchema()?.ordinaryPersistence) {
|
|
@@ -185,9 +189,10 @@ export const executeAtomicFindOneAndReplace = async <T>(
|
|
|
185
189
|
ordinaryWrite: true,
|
|
186
190
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
187
191
|
collectionName: collectionArg.collectionName,
|
|
192
|
+
timeoutMS: optionsArg.timeoutMS,
|
|
188
193
|
},
|
|
189
|
-
async (rawSessionArg) => {
|
|
190
|
-
await collectionArg.init();
|
|
194
|
+
async (rawSessionArg, deadlineArg) => {
|
|
195
|
+
await deadlineArg.join(collectionArg.init());
|
|
191
196
|
try {
|
|
192
197
|
const result = await collectionArg.mongoDbCollection.findOneAndReplace(
|
|
193
198
|
filterArg,
|
|
@@ -197,6 +202,7 @@ export const executeAtomicFindOneAndReplace = async <T>(
|
|
|
197
202
|
returnDocument: optionsArg.returnDocument,
|
|
198
203
|
upsert: false,
|
|
199
204
|
session: rawSessionArg,
|
|
205
|
+
...deadlineArg.commandOptions(),
|
|
200
206
|
},
|
|
201
207
|
);
|
|
202
208
|
const classified = classifyResult(result, {
|
|
@@ -20,6 +20,7 @@ export const executeAtomicUpdate = async <T>(
|
|
|
20
20
|
optsArg?: {
|
|
21
21
|
upsert?: boolean;
|
|
22
22
|
session?: TSmartdataOrdinarySession;
|
|
23
|
+
timeoutMS?: number;
|
|
23
24
|
},
|
|
24
25
|
): Promise<plugins.mongodb.UpdateResult> => {
|
|
25
26
|
return runWithOrdinarySmartdataSession(
|
|
@@ -29,9 +30,10 @@ export const executeAtomicUpdate = async <T>(
|
|
|
29
30
|
ordinaryWrite: true,
|
|
30
31
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
31
32
|
collectionName: collectionArg.collectionName,
|
|
33
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
32
34
|
},
|
|
33
|
-
async (rawSessionArg) => {
|
|
34
|
-
await collectionArg.init();
|
|
35
|
+
async (rawSessionArg, deadlineArg) => {
|
|
36
|
+
await deadlineArg.join(collectionArg.init());
|
|
35
37
|
try {
|
|
36
38
|
return await collectionArg.mongoDbCollection.updateOne(
|
|
37
39
|
filterArg,
|
|
@@ -39,6 +41,7 @@ export const executeAtomicUpdate = async <T>(
|
|
|
39
41
|
{
|
|
40
42
|
upsert: optsArg?.upsert === true,
|
|
41
43
|
session: rawSessionArg,
|
|
44
|
+
...deadlineArg.commandOptions(),
|
|
42
45
|
},
|
|
43
46
|
);
|
|
44
47
|
} catch (errorArg) {
|
|
@@ -83,9 +86,10 @@ export const executeAtomicUpsertMany = async <T>(
|
|
|
83
86
|
ordinaryWrite: true,
|
|
84
87
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
85
88
|
collectionName: collectionArg.collectionName,
|
|
89
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
86
90
|
},
|
|
87
|
-
async (rawSessionArg) => {
|
|
88
|
-
await collectionArg.init();
|
|
91
|
+
async (rawSessionArg, deadlineArg) => {
|
|
92
|
+
await deadlineArg.join(collectionArg.init());
|
|
89
93
|
try {
|
|
90
94
|
const result = await collectionArg.mongoDbCollection.bulkWrite(
|
|
91
95
|
operationsArg.map((operationArg) => ({
|
|
@@ -98,7 +102,7 @@ export const executeAtomicUpsertMany = async <T>(
|
|
|
98
102
|
{
|
|
99
103
|
ordered: false,
|
|
100
104
|
session: rawSessionArg,
|
|
101
|
-
|
|
105
|
+
...deadlineArg.commandOptions(),
|
|
102
106
|
},
|
|
103
107
|
);
|
|
104
108
|
return {
|
|
@@ -132,6 +136,7 @@ export const executeAtomicUpdateMany = async <T>(
|
|
|
132
136
|
updateArg: plugins.mongodb.UpdateFilter<plugins.mongodb.Document>,
|
|
133
137
|
optsArg?: {
|
|
134
138
|
session?: TSmartdataOrdinarySession;
|
|
139
|
+
timeoutMS?: number;
|
|
135
140
|
},
|
|
136
141
|
): Promise<plugins.mongodb.UpdateResult> => {
|
|
137
142
|
return runWithOrdinarySmartdataSession(
|
|
@@ -141,15 +146,17 @@ export const executeAtomicUpdateMany = async <T>(
|
|
|
141
146
|
ordinaryWrite: true,
|
|
142
147
|
prepared: collectionArg.isInitializedForCurrentDatabase(),
|
|
143
148
|
collectionName: collectionArg.collectionName,
|
|
149
|
+
timeoutMS: optsArg?.timeoutMS,
|
|
144
150
|
},
|
|
145
|
-
async (rawSessionArg) => {
|
|
146
|
-
await collectionArg.init();
|
|
151
|
+
async (rawSessionArg, deadlineArg) => {
|
|
152
|
+
await deadlineArg.join(collectionArg.init());
|
|
147
153
|
try {
|
|
148
154
|
return await collectionArg.mongoDbCollection.updateMany(
|
|
149
155
|
filterArg,
|
|
150
156
|
updateArg,
|
|
151
157
|
{
|
|
152
158
|
session: rawSessionArg,
|
|
159
|
+
...deadlineArg.commandOptions(),
|
|
153
160
|
},
|
|
154
161
|
);
|
|
155
162
|
} catch (errorArg) {
|