@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.
Files changed (51) hide show
  1. package/dist_ts/00_commitinfo_data.js +1 -1
  2. package/dist_ts/nosqldb/classes.atomicdelete.d.ts +1 -0
  3. package/dist_ts/nosqldb/classes.atomicdelete.js +10 -7
  4. package/dist_ts/nosqldb/classes.atomicfindoneandupdate.d.ts +2 -0
  5. package/dist_ts/nosqldb/classes.atomicfindoneandupdate.js +9 -5
  6. package/dist_ts/nosqldb/classes.atomicupdate.d.ts +2 -0
  7. package/dist_ts/nosqldb/classes.atomicupdate.js +13 -8
  8. package/dist_ts/nosqldb/classes.collection.d.ts +13 -4
  9. package/dist_ts/nosqldb/classes.collection.js +57 -64
  10. package/dist_ts/nosqldb/classes.db.d.ts +1 -1
  11. package/dist_ts/nosqldb/classes.doc.d.ts +60 -3
  12. package/dist_ts/nosqldb/classes.doc.js +68 -26
  13. package/dist_ts/nosqldb/classes.exactpersistence.d.ts +36 -7
  14. package/dist_ts/nosqldb/classes.exactpersistence.js +92 -81
  15. package/dist_ts/nosqldb/classes.operationdeadline.d.ts +61 -0
  16. package/dist_ts/nosqldb/classes.operationdeadline.js +149 -0
  17. package/dist_ts/nosqldb/classes.persistence.d.ts +16 -1
  18. package/dist_ts/nosqldb/classes.persistence.js +20 -1
  19. package/dist_ts/nosqldb/classes.session.d.ts +73 -2
  20. package/dist_ts/nosqldb/classes.session.js +164 -38
  21. package/dist_ts/objectstorage/classes.bucket.d.ts +61 -3
  22. package/dist_ts/objectstorage/classes.bucket.js +243 -184
  23. package/dist_ts/objectstorage/classes.directory.js +17 -28
  24. package/dist_ts/objectstorage/classes.smartbucket.d.ts +13 -6
  25. package/dist_ts/objectstorage/classes.smartbucket.js +18 -12
  26. package/dist_ts/objectstorage/classes.watcher.js +1 -2
  27. package/dist_ts/objectstorage/interfaces.d.ts +8 -0
  28. package/dist_ts/objectstorage/internal.bucketrequests.d.ts +14 -0
  29. package/dist_ts/objectstorage/internal.bucketrequests.js +53 -0
  30. package/dist_ts/objectstorage/internal.exactupload.capability.d.ts +12 -0
  31. package/dist_ts/objectstorage/internal.exactupload.capability.js +46 -17
  32. package/package.json +3 -3
  33. package/readme.md +13 -2
  34. package/ts/00_commitinfo_data.ts +1 -1
  35. package/ts/nosqldb/classes.atomicdelete.ts +10 -6
  36. package/ts/nosqldb/classes.atomicfindoneandupdate.ts +10 -4
  37. package/ts/nosqldb/classes.atomicupdate.ts +14 -7
  38. package/ts/nosqldb/classes.collection.ts +82 -73
  39. package/ts/nosqldb/classes.db.ts +1 -1
  40. package/ts/nosqldb/classes.doc.ts +162 -33
  41. package/ts/nosqldb/classes.exactpersistence.ts +131 -93
  42. package/ts/nosqldb/classes.operationdeadline.ts +179 -0
  43. package/ts/nosqldb/classes.persistence.ts +36 -1
  44. package/ts/nosqldb/classes.session.ts +221 -39
  45. package/ts/objectstorage/classes.bucket.ts +350 -218
  46. package/ts/objectstorage/classes.directory.ts +18 -27
  47. package/ts/objectstorage/classes.smartbucket.ts +21 -11
  48. package/ts/objectstorage/classes.watcher.ts +0 -1
  49. package/ts/objectstorage/interfaces.ts +9 -0
  50. package/ts/objectstorage/internal.bucketrequests.ts +70 -0
  51. 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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5vcGVyYXRpb25kZWFkbGluZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL25vc3FsZGIvY2xhc3Nlcy5vcGVyYXRpb25kZWFkbGluZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUMzQixvQkFBb0IsR0FDckIsTUFBTSwwQkFBMEIsQ0FBQztBQUVsQyxNQUFNLHVCQUF1QixHQUFHLG1EQUFtRCxDQUFDO0FBRXBGLDBGQUEwRjtBQUMxRixNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUN2QyxRQUFpQixFQUNqQixRQUFnQixFQUNJLEVBQUU7SUFDdEIsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDM0IsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztJQUNELElBQ0UsT0FBTyxRQUFRLEtBQUssUUFBUTtXQUN6QixDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsUUFBUSxDQUFDO1dBQy9CLFFBQVEsR0FBRyxDQUFDO1dBQ1osUUFBUSxHQUFHLE9BQU8sRUFDckIsQ0FBQztRQUNELE1BQU0sSUFBSSx5QkFBeUIsQ0FDakMsa0JBQWtCLEVBQ2xCLEdBQUcsUUFBUSwwREFBMEQsQ0FDdEUsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPLFFBQVEsQ0FBQztBQUNsQixDQUFDLENBQUM7QUFFRix5RUFBeUU7QUFDekUsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsQ0FDcEMsUUFBaUIsRUFDakIsUUFBZ0IsRUFDUyxFQUFFO0lBQzNCLElBQUksUUFBUSxLQUFLLFNBQVMsRUFBRSxDQUFDO1FBQzNCLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFDRCxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLENBQUMs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
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5wZXJzaXN0ZW5jZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL25vc3FsZGIvY2xhc3Nlcy5wZXJzaXN0ZW5jZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGNBQWMsQ0FBQztBQVV4Qzs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHlCQUEwQixTQUFRLEtBQUs7SUFDbEMsSUFBSSxDQUFpQztJQUVyRCxZQUNFLE9BQXVDLEVBQ3ZDLFVBQWtCLEVBQ2xCLFVBQXlCO1FBRXpCLEtBQUssQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDOUIsSUFBSSxDQUFDLElBQUksR0FBRywyQkFBMkIsQ0FBQztRQUN4QyxJQUFJLENBQUMsSUFBSSxHQUFHLE9BQU8sQ0FBQztJQUN0QixDQUFDO0NBQ0Y7QUFFRCxNQUFNLENBQUMsTUFBTSw0QkFBNEIsR0FBRyxDQUFDLFFBQWlCLEVBQVcsRUFBRSxDQUN6RSxRQUFRLFlBQVksT0FBTyxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0I7SUFDcEQsQ0FDRSxRQUFRLENBQUMsYUFBYSxDQUFDLDJCQUEyQixDQUFDO1FBQ25ELFFBQVEsQ0FBQyxhQUFhLENBQUMsZ0NBQWdDLENBQUMsQ0FDekQsQ0FBQztBQUVKLE1BQU0sQ0FBQyxNQUFNLHdCQUF3QixHQUFHLENBQ3RDLFFBQWlCLEVBQzZCLEVBQUU7SUFDaEQsT0FBTyxDQUNMLFFBQVEsWUFBWSxPQUFPLENBQUMsT0FBTyxDQUFDLGdCQUFnQjtRQUNwRCxDQUFDLFFBQVEsQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLFFBQVEsQ0FBQyxRQUFRLEtBQUssY0FBYyxDQUFDLENBQ2xFLENBQUM7QUFDSixDQUFDLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUcsQ0FDdkMsUUFBaUIsRUFDNkIsRUFBRTtJQUNoRCxPQUFPLENBQ0wsUUFBUSxZQUFZLE9BQU8sQ0FBQyxPQUFPLENBQUMsZ0JBQWdCO1FBQ3BELENBQUMsUUFBUSxDQUFDLElBQUksS0FBSyxFQUFFO1lBQ25CLFFBQVEsQ0FBQyxJQUFJLEtBQUssRUFBRTtZQUNwQixRQUFRLENBQUMsUUFBUSxLQUFLLHNCQUFzQjtZQUM1QyxRQUFRLENBQUMsUUFBUSxLQUFLLHVCQUF1QixDQUFDLENBQ2pELENBQUM7QUFDSixDQUFDLENBQUM7QUFFRixNQUFNLENBQUMsTUFBTSxpQ0FBaUMsR0FBRyxDQUMvQyxRQUFpQixFQUNqQixVQUFrQixFQUNYLEVBQUU7SUFDVCxJQUNFLFFBQVEsWUFBWSx5QkFBeUI7UUFDN0MsNEJBQTRCLENBQUMsUUFBUSxDQUFDLEVBQ3RDLENBQUM7UUFDRCxNQUFNLFFBQVEsQ0FBQztJQUNqQixDQUFDO0lBQ0QsSUFBSSx3QkFBd0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sSUFBSSx5QkFBeUIsQ0FBQyxpQkFBaUIsRUFBRSxVQUFVLEVBQUU7WUFDakUsS0FBSyxFQUFFLFFBQVE7U0FDaEIsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELE1BQU0sUUFBUSxDQUFDO0FBQ2pCLENBQUMsQ0FBQyJ9
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
- withTransaction<TResult>(callbackArg: (sessionArg: SmartdataSession) => Promise<TResult>): Promise<TResult | undefined>;
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
- export declare const runWithOrdinarySmartdataSession: <TResult>(sessionArg: TSmartdataOrdinarySession | undefined, ownerArg: SmartdataDb, optionsArg: IOrdinarySessionOperationOptions, operationArg: (rawSessionArg: plugins.mongodb.ClientSession | undefined) => Promise<TResult>) => Promise<TResult>;
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 {};