@lossless.org/client 1.6.0 → 1.8.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 +61 -3
- package/dist_ts/objectstorage/classes.bucket.js +243 -184
- 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 +3 -3
- package/readme.md +13 -2
- 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 +350 -218
- 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
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
/** Validates a caller's client deadline: a positive safe integer of at most 120000 ms. */
|
|
3
|
+
export declare const requireOperationTimeoutMS: (valueArg: unknown, labelArg: string) => number | undefined;
|
|
4
|
+
/** Validates a caller's cancellation signal: a genuine `AbortSignal`. */
|
|
5
|
+
export declare const requireOperationSignal: (valueArg: unknown, labelArg: string) => AbortSignal | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* @internal The client-side deadline and cancellation of one model API call.
|
|
8
|
+
*
|
|
9
|
+
* Every database command of the call receives the time that is left as the
|
|
10
|
+
* driver's `timeoutMS`, so server selection, connection checkout, the round
|
|
11
|
+
* trip and the server-side `maxTimeMS` the driver derives all run on one
|
|
12
|
+
* clock, and the driver closes a connection whose reply did not arrive in
|
|
13
|
+
* time. An unbounded deadline hands the driver nothing, which leaves an
|
|
14
|
+
* enclosing transaction deadline or the connection's own settings in charge.
|
|
15
|
+
*
|
|
16
|
+
* The call's `signal` — its own, an enclosing transaction's, or both — goes
|
|
17
|
+
* to the driver with every command, which stops waiting for server
|
|
18
|
+
* selection or a pooled connection and closes a connection whose command is
|
|
19
|
+
* in flight, rejecting with the signal's reason.
|
|
20
|
+
*/
|
|
21
|
+
export declare class SmartdataOperationDeadline {
|
|
22
|
+
readonly signal?: AbortSignal | undefined;
|
|
23
|
+
static readonly unbounded: SmartdataOperationDeadline;
|
|
24
|
+
private readonly expiresAt;
|
|
25
|
+
constructor(timeoutMSArg: number | undefined, signal?: AbortSignal | undefined);
|
|
26
|
+
get bounded(): boolean;
|
|
27
|
+
/** Throws the signal's reason once the call was aborted. */
|
|
28
|
+
throwIfAborted(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Driver options for one command. Throws the abort reason once the call was
|
|
31
|
+
* aborted and `timeout` once the deadline has passed, so a command these
|
|
32
|
+
* options were built for was never handed to the driver.
|
|
33
|
+
*/
|
|
34
|
+
commandOptions(): {
|
|
35
|
+
timeoutMS?: number;
|
|
36
|
+
} & plugins.mongodb.Abortable;
|
|
37
|
+
/**
|
|
38
|
+
* Driver options for a cursor the deadline bounds from its first command to
|
|
39
|
+
* its last reply. When a `getMore` times out, the driver's own cleanup runs
|
|
40
|
+
* the cursor's `killCursors` on a fresh deadline of the full `timeoutMS`
|
|
41
|
+
* before it rethrows, and no driver option shortens that, so a stalled
|
|
42
|
+
* database settles a multi-batch read within about twice the deadline.
|
|
43
|
+
*/
|
|
44
|
+
cursorOptions(): {
|
|
45
|
+
timeoutMS?: number;
|
|
46
|
+
timeoutMode?: 'cursorLifetime';
|
|
47
|
+
} & plugins.mongodb.Abortable;
|
|
48
|
+
/**
|
|
49
|
+
* Whether `errorArg` is this call's interruption: its signal's abort reason
|
|
50
|
+
* or the driver's deadline expiry.
|
|
51
|
+
*/
|
|
52
|
+
interrupted(errorArg: unknown): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Waits within the deadline for work another owner drives, such as the
|
|
55
|
+
* collection initialization every model call shares. Expiry or an abort
|
|
56
|
+
* ends only this call's wait: the owner keeps the work, its outcome and its
|
|
57
|
+
* cleanup, and the next caller joins the same work again.
|
|
58
|
+
*/
|
|
59
|
+
join(workArg: Promise<void>): Promise<void>;
|
|
60
|
+
private remainingMS;
|
|
61
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import * as plugins from './plugins.js';
|
|
2
|
+
import { SmartdataPersistenceError, createSmartdataTimeoutError, isMongoDeadlineError, } from './classes.persistence.js';
|
|
3
|
+
const deadlineExceededMessage = 'SmartData operation exceeded its client deadline.';
|
|
4
|
+
/** Validates a caller's client deadline: a positive safe integer of at most 120000 ms. */
|
|
5
|
+
export const requireOperationTimeoutMS = (valueArg, labelArg) => {
|
|
6
|
+
if (valueArg === undefined) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
if (typeof valueArg !== 'number'
|
|
10
|
+
|| !Number.isSafeInteger(valueArg)
|
|
11
|
+
|| valueArg < 1
|
|
12
|
+
|| valueArg > 120_000) {
|
|
13
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be a positive safe integer no greater than 120000.`);
|
|
14
|
+
}
|
|
15
|
+
return valueArg;
|
|
16
|
+
};
|
|
17
|
+
/** Validates a caller's cancellation signal: a genuine `AbortSignal`. */
|
|
18
|
+
export const requireOperationSignal = (valueArg, labelArg) => {
|
|
19
|
+
if (valueArg === undefined) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
if (plugins.nodeUtil.types.isProxy(valueArg) || !(valueArg instanceof AbortSignal)) {
|
|
23
|
+
throw new SmartdataPersistenceError('invalid_argument', `${labelArg} must be an AbortSignal.`);
|
|
24
|
+
}
|
|
25
|
+
return valueArg;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* @internal The client-side deadline and cancellation of one model API call.
|
|
29
|
+
*
|
|
30
|
+
* Every database command of the call receives the time that is left as the
|
|
31
|
+
* driver's `timeoutMS`, so server selection, connection checkout, the round
|
|
32
|
+
* trip and the server-side `maxTimeMS` the driver derives all run on one
|
|
33
|
+
* clock, and the driver closes a connection whose reply did not arrive in
|
|
34
|
+
* time. An unbounded deadline hands the driver nothing, which leaves an
|
|
35
|
+
* enclosing transaction deadline or the connection's own settings in charge.
|
|
36
|
+
*
|
|
37
|
+
* The call's `signal` — its own, an enclosing transaction's, or both — goes
|
|
38
|
+
* to the driver with every command, which stops waiting for server
|
|
39
|
+
* selection or a pooled connection and closes a connection whose command is
|
|
40
|
+
* in flight, rejecting with the signal's reason.
|
|
41
|
+
*/
|
|
42
|
+
export class SmartdataOperationDeadline {
|
|
43
|
+
signal;
|
|
44
|
+
static unbounded = new SmartdataOperationDeadline(undefined);
|
|
45
|
+
expiresAt;
|
|
46
|
+
constructor(timeoutMSArg, signal) {
|
|
47
|
+
this.signal = signal;
|
|
48
|
+
this.expiresAt = timeoutMSArg === undefined
|
|
49
|
+
? undefined
|
|
50
|
+
: performance.now() + timeoutMSArg;
|
|
51
|
+
}
|
|
52
|
+
get bounded() {
|
|
53
|
+
return this.expiresAt !== undefined;
|
|
54
|
+
}
|
|
55
|
+
/** Throws the signal's reason once the call was aborted. */
|
|
56
|
+
throwIfAborted() {
|
|
57
|
+
this.signal?.throwIfAborted();
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Driver options for one command. Throws the abort reason once the call was
|
|
61
|
+
* aborted and `timeout` once the deadline has passed, so a command these
|
|
62
|
+
* options were built for was never handed to the driver.
|
|
63
|
+
*/
|
|
64
|
+
commandOptions() {
|
|
65
|
+
this.throwIfAborted();
|
|
66
|
+
return {
|
|
67
|
+
...(this.expiresAt === undefined ? {} : { timeoutMS: this.remainingMS() }),
|
|
68
|
+
...(this.signal === undefined ? {} : { signal: this.signal }),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Driver options for a cursor the deadline bounds from its first command to
|
|
73
|
+
* its last reply. When a `getMore` times out, the driver's own cleanup runs
|
|
74
|
+
* the cursor's `killCursors` on a fresh deadline of the full `timeoutMS`
|
|
75
|
+
* before it rethrows, and no driver option shortens that, so a stalled
|
|
76
|
+
* database settles a multi-batch read within about twice the deadline.
|
|
77
|
+
*/
|
|
78
|
+
cursorOptions() {
|
|
79
|
+
this.throwIfAborted();
|
|
80
|
+
return {
|
|
81
|
+
...(this.expiresAt === undefined
|
|
82
|
+
? {}
|
|
83
|
+
: { timeoutMS: this.remainingMS(), timeoutMode: 'cursorLifetime' }),
|
|
84
|
+
...(this.signal === undefined ? {} : { signal: this.signal }),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Whether `errorArg` is this call's interruption: its signal's abort reason
|
|
89
|
+
* or the driver's deadline expiry.
|
|
90
|
+
*/
|
|
91
|
+
interrupted(errorArg) {
|
|
92
|
+
return (this.signal?.aborted === true && errorArg === this.signal.reason)
|
|
93
|
+
|| isMongoDeadlineError(errorArg);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Waits within the deadline for work another owner drives, such as the
|
|
97
|
+
* collection initialization every model call shares. Expiry or an abort
|
|
98
|
+
* ends only this call's wait: the owner keeps the work, its outcome and its
|
|
99
|
+
* cleanup, and the next caller joins the same work again.
|
|
100
|
+
*/
|
|
101
|
+
async join(workArg) {
|
|
102
|
+
this.throwIfAborted();
|
|
103
|
+
if (this.expiresAt === undefined && this.signal === undefined) {
|
|
104
|
+
await workArg;
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const remainingMS = this.expiresAt === undefined ? undefined : this.remainingMS();
|
|
108
|
+
let timer;
|
|
109
|
+
let onAbort;
|
|
110
|
+
let expired = false;
|
|
111
|
+
const interruption = new Promise((resolveArg) => {
|
|
112
|
+
if (remainingMS !== undefined) {
|
|
113
|
+
timer = setTimeout(() => {
|
|
114
|
+
expired = true;
|
|
115
|
+
resolveArg();
|
|
116
|
+
}, remainingMS);
|
|
117
|
+
}
|
|
118
|
+
if (this.signal !== undefined) {
|
|
119
|
+
onAbort = () => resolveArg();
|
|
120
|
+
this.signal.addEventListener('abort', onAbort, { once: true });
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
// The owner observes the work's failure itself; this wait must not turn a
|
|
124
|
+
// failure it stopped waiting for into an unhandled rejection.
|
|
125
|
+
const settled = workArg.then(() => undefined, () => undefined);
|
|
126
|
+
try {
|
|
127
|
+
await Promise.race([settled, interruption]);
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
clearTimeout(timer);
|
|
131
|
+
if (onAbort !== undefined) {
|
|
132
|
+
this.signal?.removeEventListener('abort', onAbort);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
this.throwIfAborted();
|
|
136
|
+
if (expired) {
|
|
137
|
+
throw createSmartdataTimeoutError(deadlineExceededMessage);
|
|
138
|
+
}
|
|
139
|
+
await workArg;
|
|
140
|
+
}
|
|
141
|
+
remainingMS() {
|
|
142
|
+
const remainingMS = this.expiresAt - performance.now();
|
|
143
|
+
if (remainingMS <= 0) {
|
|
144
|
+
throw createSmartdataTimeoutError(deadlineExceededMessage);
|
|
145
|
+
}
|
|
146
|
+
return Math.ceil(remainingMS);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVyYXRpb25kZWFkbGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL25vc3FsZGIvY2xhc3Nlcy5vcGVyYXRpb25kZWFkbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUMzQixvQkFBb0IsR0FDckIsTUFBTSwwQkFBMEIsQ0FBQztBQUVsQyxNQUFNLHVCQUF1QixHQUFHLG1EQUFtRCxDQUFDO0FBRXBGLDBGQUEwRjtBQUMxRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxRQUFpQixFQUNqQixRQUFnQixFQUNJLEVBQUU7SUFDdEIsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDM0IsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELElBQ0UsT0FBTyxRQUFRLEtBQUssUUFBUTtXQUN6QixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO1dBQy9CLFFBQVEsR0FBRyxDQUFDO1dBQ1osUUFBUSxHQUFHLE9BQU8sRUFDckIsQ0FBQztRQUNELE1BQU0sSUFBSSx5QkFBeUIsQ0FDakMsa0JBQWtCLEVBQ2xCLEdBQUcsUUFBUSwwREFBMEQsQ0FDdEUsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRix5RUFBeUU7QUFDekUsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FDcEMsUUFBaUIsRUFDakIsUUFBZ0IsRUFDUyxFQUFFO0lBQzNCLElBQUksUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxZQUFZLFdBQVcsQ0FBQyxFQUFFLENBQUM7UUFDbkYsTUFBTSxJQUFJLHlCQUF5QixDQUFDLGtCQUFrQixFQUFFLEdBQUcsUUFBUSwwQkFBMEIsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRjs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE1BQU0sT0FBTywwQkFBMEI7SUFPbkI7SUFOWCxNQUFNLENBQVUsU0FBUyxHQUFHLElBQUksMEJBQTBCLENBQUMsU0FBUyxDQUFDLENBQUM7SUFFNUQsU0FBUyxDQUFxQjtJQUUvQyxZQUNFLFlBQWdDLEVBQ2hCLE1BQW9CO1FBQXBCLFdBQU0sR0FBTixNQUFNLENBQWM7UUFFcEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxZQUFZLEtBQUssU0FBUztZQUN6QyxDQUFDLENBQUMsU0FBUztZQUNYLENBQUMsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLEdBQUcsWUFBWSxDQUFDO0lBQ3ZDLENBQUM7SUFFRCxJQUFXLE9BQU87UUFDaEIsT0FBTyxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQztJQUN0QyxDQUFDO0lBRUQsNERBQTREO0lBQ3JELGNBQWM7UUFDbkIsSUFBSSxDQUFDLE1BQU0sRUFBRSxjQUFjLEVBQUUsQ0FBQztJQUNoQyxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNJLGNBQWM7UUFDbkIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLE9BQU87WUFDTCxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUM7WUFDMUUsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztTQUM5RCxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNJLGFBQWE7UUFJbEIsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLE9BQU87WUFDTCxHQUFHLENBQUMsSUFBSSxDQUFDLFNBQVMsS0FBSyxTQUFTO2dCQUM5QixDQUFDLENBQUMsRUFBRTtnQkFDSixDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLFdBQVcsRUFBRSxnQkFBeUIsRUFBRSxDQUFDO1lBQzlFLEdBQUcsQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7U0FDOUQsQ0FBQztJQUNKLENBQUM7SUFFRDs7O09BR0c7SUFDSSxXQUFXLENBQUMsUUFBaUI7UUFDbEMsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsT0FBTyxLQUFLLElBQUksSUFBSSxRQUFRLEtBQUssSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7ZUFDcEUsb0JBQW9CLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0ksS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFzQjtRQUN0QyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdEIsSUFBSSxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQzlELE1BQU0sT0FBTyxDQUFDO1lBQ2QsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbEYsSUFBSSxLQUFnRCxDQUFDO1FBQ3JELElBQUksT0FBaUMsQ0FBQztRQUN0QyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDcEIsTUFBTSxZQUFZLEdBQUcsSUFBSSxPQUFPLENBQU8sQ0FBQyxVQUFVLEVBQUUsRUFBRTtZQUNwRCxJQUFJLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDOUIsS0FBSyxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7b0JBQ3RCLE9BQU8sR0FBRyxJQUFJLENBQUM7b0JBQ2YsVUFBVSxFQUFFLENBQUM7Z0JBQ2YsQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQ2xCLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzlCLE9BQU8sR0FBRyxHQUFHLEVBQUUsQ0FBQyxVQUFVLEVBQUUsQ0FBQztnQkFDN0IsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7WUFDakUsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsMEVBQTBFO1FBQzFFLDhEQUE4RDtRQUM5RCxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMvRCxJQUFJLENBQUM7WUFDSCxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxDQUFDLENBQUMsQ0FBQztRQUM5QyxDQUFDO2dCQUFTLENBQUM7WUFDVCxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDcEIsSUFBSSxPQUFPLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQzFCLElBQUksQ0FBQyxNQUFNLEVBQUUsbUJBQW1CLENBQUMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1lBQ3JELENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3RCLElBQUksT0FBTyxFQUFFLENBQUM7WUFDWixNQUFNLDJCQUEyQixDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDN0QsQ0FBQztRQUNELE1BQU0sT0FBTyxDQUFDO0lBQ2hCLENBQUM7SUFFTyxXQUFXO1FBQ2pCLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxTQUFVLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3hELElBQUksV0FBVyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3JCLE1BQU0sMkJBQTJCLENBQUMsdUJBQXVCLENBQUMsQ0FBQztRQUM3RCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQ2hDLENBQUMifQ==
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
-
export type TSmartdataPersistenceErrorCode = 'invalid_argument' | 'invalid_configuration' | 'invalid_document' | 'unique_conflict' | 'ambiguous_write' | 'unsupported_operation';
|
|
2
|
+
export type TSmartdataPersistenceErrorCode = 'invalid_argument' | 'invalid_configuration' | 'invalid_document' | 'unique_conflict' | 'ambiguous_write' | 'unsupported_operation' | 'timeout';
|
|
3
3
|
/**
|
|
4
4
|
* Stable errors for ordinary SmartData model configuration and persistence.
|
|
5
5
|
*
|
|
@@ -9,6 +9,21 @@ export declare class SmartdataPersistenceError extends Error {
|
|
|
9
9
|
readonly code: TSmartdataPersistenceErrorCode;
|
|
10
10
|
constructor(codeArg: TSmartdataPersistenceErrorCode, messageArg: string, optionsArg?: ErrorOptions);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The client-side deadline of a model call or transaction expired. The
|
|
14
|
+
* driver's own `MongoOperationTimeoutError` stays available as `cause` when
|
|
15
|
+
* the driver enforced it. A write or commit that expired has an unknown
|
|
16
|
+
* outcome: it may have been applied before the reply was lost.
|
|
17
|
+
*/
|
|
18
|
+
export declare const createSmartdataTimeoutError: (messageArg: string, causeArg?: unknown) => SmartdataPersistenceError;
|
|
19
|
+
/**
|
|
20
|
+
* The driver enforced a client deadline. A bulk write reports a driver error
|
|
21
|
+
* wrapped in `MongoBulkWriteError`, whose `errorResponse` is the original
|
|
22
|
+
* error and whose result still states what earlier batches wrote.
|
|
23
|
+
*/
|
|
24
|
+
export declare const isMongoDeadlineError: (errorArg: unknown) => boolean;
|
|
25
|
+
/** Maps an expired driver deadline to `timeout`; every other error passes through unchanged. */
|
|
26
|
+
export declare const normalizeDeadlineError: (errorArg: unknown) => unknown;
|
|
12
27
|
export declare const isMongoTransactionRetryError: (errorArg: unknown) => boolean;
|
|
13
28
|
export declare const isMongoDuplicateKeyError: (errorArg: unknown) => errorArg is plugins.mongodb.MongoServerError;
|
|
14
29
|
/**
|
|
@@ -12,6 +12,25 @@ export class SmartdataPersistenceError extends Error {
|
|
|
12
12
|
this.code = codeArg;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
+
/**
|
|
16
|
+
* The client-side deadline of a model call or transaction expired. The
|
|
17
|
+
* driver's own `MongoOperationTimeoutError` stays available as `cause` when
|
|
18
|
+
* the driver enforced it. A write or commit that expired has an unknown
|
|
19
|
+
* outcome: it may have been applied before the reply was lost.
|
|
20
|
+
*/
|
|
21
|
+
export const createSmartdataTimeoutError = (messageArg, causeArg) => new SmartdataPersistenceError('timeout', messageArg, causeArg === undefined ? undefined : { cause: causeArg });
|
|
22
|
+
/**
|
|
23
|
+
* The driver enforced a client deadline. A bulk write reports a driver error
|
|
24
|
+
* wrapped in `MongoBulkWriteError`, whose `errorResponse` is the original
|
|
25
|
+
* error and whose result still states what earlier batches wrote.
|
|
26
|
+
*/
|
|
27
|
+
export const isMongoDeadlineError = (errorArg) => errorArg instanceof plugins.mongodb.MongoOperationTimeoutError
|
|
28
|
+
|| (errorArg instanceof plugins.mongodb.MongoBulkWriteError
|
|
29
|
+
&& errorArg.errorResponse instanceof plugins.mongodb.MongoOperationTimeoutError);
|
|
30
|
+
/** Maps an expired driver deadline to `timeout`; every other error passes through unchanged. */
|
|
31
|
+
export const normalizeDeadlineError = (errorArg) => isMongoDeadlineError(errorArg)
|
|
32
|
+
? createSmartdataTimeoutError('SmartData operation exceeded its client deadline.', errorArg)
|
|
33
|
+
: errorArg;
|
|
15
34
|
export const isMongoTransactionRetryError = (errorArg) => errorArg instanceof plugins.mongodb.MongoServerError &&
|
|
16
35
|
(errorArg.hasErrorLabel('TransientTransactionError') ||
|
|
17
36
|
errorArg.hasErrorLabel('UnknownTransactionCommitResult'));
|
|
@@ -43,4 +62,4 @@ export const normalizeOrdinaryPersistenceError = (errorArg, messageArg) => {
|
|
|
43
62
|
}
|
|
44
63
|
throw errorArg;
|
|
45
64
|
};
|
|
46
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
65
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wZXJzaXN0ZW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL25vc3FsZGIvY2xhc3Nlcy5wZXJzaXN0ZW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQVd4Qzs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHlCQUEwQixTQUFRLEtBQUs7SUFDbEMsSUFBSSxDQUFpQztJQUVyRCxZQUNFLE9BQXVDLEVBQ3ZDLFVBQWtCLEVBQ2xCLFVBQXlCO1FBRXpCLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRywyQkFBMkIsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztJQUN0QixDQUFDO0NBQ0Y7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFHLENBQ3pDLFVBQWtCLEVBQ2xCLFFBQWtCLEVBQ1MsRUFBRSxDQUM3QixJQUFJLHlCQUF5QixDQUMzQixTQUFTLEVBQ1QsVUFBVSxFQUNWLFFBQVEsS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLENBQ3pELENBQUM7QUFFSjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sb0JBQW9CLEdBQUcsQ0FBQyxRQUFpQixFQUFXLEVBQUUsQ0FDakUsUUFBUSxZQUFZLE9BQU8sQ0FBQyxPQUFPLENBQUMsMEJBQTBCO09BQzNELENBQ0QsUUFBUSxZQUFZLE9BQU8sQ0FBQyxPQUFPLENBQUMsbUJBQW1CO1dBQ3BELFFBQVEsQ0FBQyxhQUFhLFlBQVksT0FBTyxDQUFDLE9BQU8sQ0FBQywwQkFBMEIsQ0FDaEYsQ0FBQztBQUVKLGdHQUFnRztBQUNoRyxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLFFBQWlCLEVBQVcsRUFBRSxDQUNuRSxvQkFBb0IsQ0FBQyxRQUFRLENBQUM7SUFDNUIsQ0FBQyxDQUFDLDJCQUEyQixDQUFDLG1EQUFtRCxFQUFFLFFBQVEsQ0FBQztJQUM1RixDQUFDLENBQUMsUUFBUSxDQUFDO0FBRWYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsQ0FBQyxRQUFpQixFQUFXLEVBQUUsQ0FDekUsUUFBUSxZQUFZLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO0lBQ3BELENBQ0UsUUFBUSxDQUFDLGFBQWEsQ0FBQywyQkFBMkIsQ0FBQztRQUNuRCxRQUFRLENBQUMsYUFBYSxDQUFDLGdDQUFnQyxDQUFDLENBQ3pELENBQUM7QUFFSixNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxDQUN0QyxRQUFpQixFQUM2QixFQUFFO0lBQ2hELE9BQU8sQ0FDTCxRQUFRLFlBQVksT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7UUFDcEQsQ0FBQyxRQUFRLENBQUMsSUFBSSxLQUFLLEtBQUssSUFBSSxRQUFRLENBQUMsUUFBUSxLQUFLLGNBQWMsQ0FBQyxDQUNsRSxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUY7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLHlCQUF5QixHQUFHLENBQ3ZDLFFBQWlCLEVBQzZCLEVBQUU7SUFDaEQsT0FBTyxDQUNMLFFBQVEsWUFBWSxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtRQUNwRCxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssRUFBRTtZQUNuQixRQUFRLENBQUMsSUFBSSxLQUFLLEVBQUU7WUFDcEIsUUFBUSxDQUFDLFFBQVEsS0FBSyxzQkFBc0I7WUFDNUMsUUFBUSxDQUFDLFFBQVEsS0FBSyx1QkFBdUIsQ0FBQyxDQUNqRCxDQUFDO0FBQ0osQ0FBQyxDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0saUNBQWlDLEdBQUcsQ0FDL0MsUUFBaUIsRUFDakIsVUFBa0IsRUFDWCxFQUFFO0lBQ1QsSUFDRSxRQUFRLFlBQVkseUJBQXlCO1FBQzdDLDRCQUE0QixDQUFDLFFBQVEsQ0FBQyxFQUN0QyxDQUFDO1FBQ0QsTUFBTSxRQUFRLENBQUM7SUFDakIsQ0FBQztJQUNELElBQUksd0JBQXdCLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUN2QyxNQUFNLElBQUkseUJBQXlCLENBQUMsaUJBQWlCLEVBQUUsVUFBVSxFQUFFO1lBQ2pFLEtBQUssRUFBRSxRQUFRO1NBQ2hCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxNQUFNLFFBQVEsQ0FBQztBQUNqQixDQUFDLENBQUMifQ==
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import type { SmartdataDb } from './classes.db.js';
|
|
3
|
+
import { SmartdataOperationDeadline } from './classes.operationdeadline.js';
|
|
3
4
|
interface ISmartdataSessionAcquireOptions {
|
|
4
5
|
ordinaryWrite?: boolean;
|
|
5
6
|
}
|
|
@@ -8,9 +9,56 @@ interface IOrdinarySessionOperationOptions {
|
|
|
8
9
|
prepared?: boolean;
|
|
9
10
|
/** Names the collection whose preparation a refusal must ask for. */
|
|
10
11
|
collectionName?: string;
|
|
12
|
+
/** The caller's validated client deadline for the call's database work. */
|
|
13
|
+
timeoutMS?: number;
|
|
14
|
+
/** The API's own default deadline; a transaction deadline replaces it. */
|
|
15
|
+
defaultTimeoutMS?: number;
|
|
16
|
+
/** The caller's validated cancellation signal for the call's database work. */
|
|
17
|
+
signal?: AbortSignal;
|
|
18
|
+
}
|
|
19
|
+
export interface ISmartdataTransactionOptions {
|
|
20
|
+
/**
|
|
21
|
+
* Client deadline for the whole transaction (1..120000 ms): every attempt,
|
|
22
|
+
* the operations the callback runs on the session, the driver's retries and
|
|
23
|
+
* the commit. Operations inside take no `timeoutMS` of their own.
|
|
24
|
+
*/
|
|
25
|
+
timeoutMS?: number;
|
|
26
|
+
/**
|
|
27
|
+
* Cancels the transaction. Every operation the callback runs on the session
|
|
28
|
+
* observes it: the one in flight is interrupted and every later one is
|
|
29
|
+
* refused with the abort reason. An aborted transaction is rolled back and
|
|
30
|
+
* never committed; a commit already sent runs to its own outcome.
|
|
31
|
+
*/
|
|
32
|
+
signal?: AbortSignal;
|
|
11
33
|
}
|
|
12
34
|
export declare class SmartdataSession {
|
|
13
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Runs `callbackArg` in a transaction, retrying it as the driver decides.
|
|
37
|
+
*
|
|
38
|
+
* `timeoutMS` bounds the whole transaction through the driver's client-side
|
|
39
|
+
* operation timeout. When it expires the call rejects with a
|
|
40
|
+
* `SmartdataPersistenceError` of code `timeout`: before the commit was sent
|
|
41
|
+
* nothing was committed, during the commit the outcome is unknown. When the
|
|
42
|
+
* deadline expires inside the callback, the driver's closing
|
|
43
|
+
* `abortTransaction` runs on a fresh deadline of the same length, so a
|
|
44
|
+
* stalled database settles the call within about twice `timeoutMS`.
|
|
45
|
+
*
|
|
46
|
+
* `signal` cancels the transaction. An abort before the call rejects with
|
|
47
|
+
* the abort reason at once. An abort while the callback runs interrupts the
|
|
48
|
+
* operation in flight on the session and refuses every later one with the
|
|
49
|
+
* reason; once the callback has settled, the driver's `abortTransaction`
|
|
50
|
+
* rolls the attempt back and the call rejects with the reason, even when
|
|
51
|
+
* the callback caught it, and no further attempt starts. The driver cannot
|
|
52
|
+
* cancel a commit in flight, so an abort that arrives after the commit was
|
|
53
|
+
* sent leaves the commit to its own outcome: the call returns the result
|
|
54
|
+
* when it committed, and rejects with `timeout` ("the commit outcome is
|
|
55
|
+
* unknown") when the deadline expired during it.
|
|
56
|
+
*
|
|
57
|
+
* Any operation on the session that its deadline or a signal interrupts
|
|
58
|
+
* fails the attempt: the call rolls it back and rejects with that
|
|
59
|
+
* operation's error even when the callback caught it.
|
|
60
|
+
*/
|
|
61
|
+
withTransaction<TResult>(callbackArg: (sessionArg: SmartdataSession) => Promise<TResult>, optionsArg?: ISmartdataTransactionOptions): Promise<TResult | undefined>;
|
|
14
62
|
close(): Promise<void>;
|
|
15
63
|
}
|
|
16
64
|
export declare const createSmartdataSession: (ownerArg: SmartdataDb) => SmartdataSession;
|
|
@@ -36,7 +84,30 @@ export declare const leaseOrdinarySmartdataSession: (sessionArg: TSmartdataOrdin
|
|
|
36
84
|
rawSession: plugins.mongodb.ClientSession | undefined;
|
|
37
85
|
release: () => void;
|
|
38
86
|
};
|
|
39
|
-
|
|
87
|
+
/**
|
|
88
|
+
* The deadline and signal one operation runs under. Inside an owned
|
|
89
|
+
* transaction with a deadline, the transaction's deadline bounds the
|
|
90
|
+
* operation through the session, and the driver refuses a second one on the
|
|
91
|
+
* same session, so an explicit operation deadline is refused and a default
|
|
92
|
+
* one is dropped. Inside an owned transaction with a signal, the operation
|
|
93
|
+
* observes that signal beside its own.
|
|
94
|
+
*/
|
|
95
|
+
export declare const resolveSmartdataOperationDeadline: (sessionArg: TSmartdataOrdinarySession | undefined, optionsArg: Pick<IOrdinarySessionOperationOptions, "timeoutMS" | "defaultTimeoutMS" | "signal">) => SmartdataOperationDeadline;
|
|
96
|
+
/**
|
|
97
|
+
* The error one operation on the session boundary rejects with: an expired
|
|
98
|
+
* driver deadline becomes the `timeout` persistence error, everything else
|
|
99
|
+
* passes through. An operation its deadline or signal interrupted inside an
|
|
100
|
+
* owned transaction also fails the transaction attempt, so `withTransaction`
|
|
101
|
+
* rolls it back and rejects with that error even when the callback caught it:
|
|
102
|
+
* whatever the interrupted command did inside the transaction is unknown.
|
|
103
|
+
*/
|
|
104
|
+
export declare const settleSmartdataOperationError: (sessionArg: TSmartdataOrdinarySession | undefined, deadlineArg: SmartdataOperationDeadline, errorArg: unknown) => unknown;
|
|
105
|
+
/**
|
|
106
|
+
* Runs one model operation on the ordinary session boundary: the owned
|
|
107
|
+
* session lease, the operation's client deadline and signal, and the mapping
|
|
108
|
+
* of an expired driver deadline to the `timeout` persistence error.
|
|
109
|
+
*/
|
|
110
|
+
export declare const runWithOrdinarySmartdataSession: <TResult>(sessionArg: TSmartdataOrdinarySession | undefined, ownerArg: SmartdataDb, optionsArg: IOrdinarySessionOperationOptions, operationArg: (rawSessionArg: plugins.mongodb.ClientSession | undefined, deadlineArg: SmartdataOperationDeadline) => Promise<TResult>) => Promise<TResult>;
|
|
40
111
|
export declare const invalidateSmartdataSessions: (ownerArg: SmartdataDb) => Promise<void>;
|
|
41
112
|
export declare const unwrapSmartdataSessionInvalidationErrors: (errorArg: unknown) => readonly unknown[] | undefined;
|
|
42
113
|
export {};
|