@matter/general 0.13.1-alpha.0-20250520-d699cd56d → 0.14.0-alpha.0-20250521-979eda05d

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 (42) hide show
  1. package/dist/cjs/polyfills/index.d.ts +1 -0
  2. package/dist/cjs/polyfills/index.d.ts.map +1 -1
  3. package/dist/cjs/polyfills/index.js +1 -0
  4. package/dist/cjs/polyfills/index.js.map +1 -1
  5. package/dist/cjs/polyfills/suppressed-error.d.ts +7 -0
  6. package/dist/cjs/polyfills/suppressed-error.d.ts.map +1 -0
  7. package/dist/cjs/polyfills/suppressed-error.js +21 -0
  8. package/dist/cjs/polyfills/suppressed-error.js.map +6 -0
  9. package/dist/cjs/transaction/Transaction.d.ts +32 -5
  10. package/dist/cjs/transaction/Transaction.d.ts.map +1 -1
  11. package/dist/cjs/transaction/Transaction.js +22 -3
  12. package/dist/cjs/transaction/Transaction.js.map +1 -1
  13. package/dist/cjs/transaction/Tx.d.ts +9 -4
  14. package/dist/cjs/transaction/Tx.d.ts.map +1 -1
  15. package/dist/cjs/transaction/Tx.js +152 -122
  16. package/dist/cjs/transaction/Tx.js.map +2 -2
  17. package/dist/cjs/util/Observable.js +1 -1
  18. package/dist/cjs/util/Observable.js.map +1 -1
  19. package/dist/esm/polyfills/index.d.ts +1 -0
  20. package/dist/esm/polyfills/index.d.ts.map +1 -1
  21. package/dist/esm/polyfills/index.js +1 -0
  22. package/dist/esm/polyfills/index.js.map +1 -1
  23. package/dist/esm/polyfills/suppressed-error.d.ts +7 -0
  24. package/dist/esm/polyfills/suppressed-error.d.ts.map +1 -0
  25. package/dist/esm/polyfills/suppressed-error.js +20 -0
  26. package/dist/esm/polyfills/suppressed-error.js.map +6 -0
  27. package/dist/esm/transaction/Transaction.d.ts +32 -5
  28. package/dist/esm/transaction/Transaction.d.ts.map +1 -1
  29. package/dist/esm/transaction/Transaction.js +23 -4
  30. package/dist/esm/transaction/Transaction.js.map +1 -1
  31. package/dist/esm/transaction/Tx.d.ts +9 -4
  32. package/dist/esm/transaction/Tx.d.ts.map +1 -1
  33. package/dist/esm/transaction/Tx.js +152 -122
  34. package/dist/esm/transaction/Tx.js.map +2 -2
  35. package/dist/esm/util/Observable.js +1 -1
  36. package/dist/esm/util/Observable.js.map +1 -1
  37. package/package.json +2 -2
  38. package/src/polyfills/index.ts +1 -0
  39. package/src/polyfills/suppressed-error.ts +27 -0
  40. package/src/transaction/Transaction.ts +42 -4
  41. package/src/transaction/Tx.ts +202 -165
  42. package/src/util/Observable.ts +1 -1
@@ -4,4 +4,5 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import "./disposable.js";
7
+ import "./suppressed-error.js";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/polyfills/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/polyfills/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,iBAAiB,CAAC;AACzB,OAAO,uBAAuB,CAAC"}
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  var import_disposable = require("./disposable.js");
3
+ var import_suppressed_error = require("./suppressed-error.js");
3
4
  /**
4
5
  * @license
5
6
  * Copyright 2022-2025 Matter.js Authors
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/polyfills/index.ts"],
4
- "mappings": ";AAMA,wBAAO;AANP;AAAA;AAAA;AAAA;AAAA;",
4
+ "mappings": ";AAMA,wBAAO;AACP,8BAAO;AAPP;AAAA;AAAA;AAAA;AAAA;",
5
5
  "names": []
6
6
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2022-2025 Project CHIP Authors
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
7
+ //# sourceMappingURL=suppressed-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"suppressed-error.d.ts","sourceRoot":"","sources":["../../../src/polyfills/suppressed-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ /**
3
+ * @license
4
+ * Copyright 2022-2025 Project CHIP Authors
5
+ * SPDX-License-Identifier: Apache-2.0
6
+ */
7
+ if (globalThis.SuppressedError === void 0) {
8
+ class SuppressedError extends Error {
9
+ error;
10
+ suppressed;
11
+ constructor(error, suppressed, message) {
12
+ super(message);
13
+ this.error = error;
14
+ this.suppressed = suppressed;
15
+ }
16
+ }
17
+ const factory = (error, suppressed, message) => new SuppressedError(error, suppressed, message);
18
+ factory.prototype = SuppressedError.prototype;
19
+ globalThis.SuppressedError = factory;
20
+ }
21
+ //# sourceMappingURL=suppressed-error.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/polyfills/suppressed-error.ts"],
4
+ "mappings": ";AAAA;AAAA;AAAA;AAAA;AAAA;AAMA,IAAI,WAAW,oBAAoB,QAAW;AAAA,EAI1C,MAAM,wBAAwB,MAAM;AAAA,IAChC;AAAA,IACA;AAAA,IAEA,YAAY,OAAY,YAAiB,SAAkB;AACvD,YAAM,OAAO;AAEb,WAAK,QAAQ;AACb,WAAK,aAAa;AAAA,IACtB;AAAA,EACJ;AAEA,QAAM,UAAU,CAAC,OAAY,YAAiB,YAAqB,IAAI,gBAAgB,OAAO,YAAY,OAAO;AACjH,UAAQ,YAAY,gBAAgB;AAEpC,aAAW,kBAAkB;AACjC;",
5
+ "names": []
6
+ }
@@ -134,7 +134,9 @@ type ResourceSetType = ResourceSet;
134
134
  type ParticipantType = Participant;
135
135
  export declare const Transaction: {
136
136
  /**
137
- * Perform a transactional operation. This is the only way to obtain a read/write transaction.
137
+ * Perform a transactional operation.
138
+ *
139
+ * This creates a read/write transaction scoped to the life of an optionally async function call.
138
140
  *
139
141
  * The transaction will commit automatically if it is exclusive (write mode) after the actor returns.
140
142
  *
@@ -142,6 +144,14 @@ export declare const Transaction: {
142
144
  * destroyed.
143
145
  */
144
146
  act<T>(via: string, actor: (transaction: Transaction) => MaybePromise<T>): MaybePromise<T>;
147
+ /**
148
+ * Create a transaction.
149
+ *
150
+ * Transactions must be closed using {@link Finalization#resolve} or {@link Finalization#reject}.
151
+ *
152
+ * When closed the transaction commits automatically if exclusive.
153
+ */
154
+ open(via: string): Transaction & Transaction.Finalization;
145
155
  ReadOnly: {
146
156
  "__#15458@#participants": Set<Participant>;
147
157
  "__#15458@#roles": Map<{}, Participant>;
@@ -153,7 +163,6 @@ export declare const Transaction: {
153
163
  "__#15458@#closed"?: import("../index.js").Observable<[]>;
154
164
  "__#15458@#isAsync": boolean;
155
165
  "__#15458@#reportingLocks": boolean;
156
- close(): void;
157
166
  readonly via: string;
158
167
  readonly status: Status;
159
168
  readonly participants: Set<Participant>;
@@ -169,20 +178,25 @@ export declare const Transaction: {
169
178
  beginSync(): void;
170
179
  addParticipants(...participants: Participant[]): void;
171
180
  getParticipant(role: {}): Participant | undefined;
172
- commit(): MaybePromise;
181
+ commit(): MaybePromise<void>;
182
+ resolve<T>(result: T): MaybePromise<Awaited<T>>;
173
183
  rollback(): Promise<void> | undefined;
184
+ reject(cause: unknown): MaybePromise<never>;
185
+ "__#15458@#executeCommitCycle"(count: number): MaybePromise<void>;
174
186
  waitFor(others: Set<Transaction>): Promise<void>;
175
187
  toString(): string;
176
188
  treatAsSlow(): void;
177
189
  "__#15458@#finalize"(status: Status, why: string, finalizer: () => MaybePromise): Promise<void> | undefined;
178
- "__#15458@#executePreCommit"(): MaybePromise<void>;
190
+ "__#15458@#reset"(why: string): void;
191
+ "__#15458@#createPreCommitExecutor"(): () => MaybePromise<void>;
179
192
  "__#15458@#executeCommit"(): MaybePromise;
180
193
  "__#15458@#executeCommit1"(): MaybePromise;
181
194
  "__#15458@#executeCommit2"(): Promise<void> | undefined;
182
- "__#15458@#executePostCommit"(participants: Participant[]): MaybePromise;
195
+ "__#15458@#createPostCommitExecutor"(participants: Participant[]): () => MaybePromise;
183
196
  "__#15458@#executeRollback"(): Promise<void> | undefined;
184
197
  "__#15458@#locksChanged"(resources: Set<Resource>, how?: string): void;
185
198
  "__#15458@#assertAvailable"(): void;
199
+ [Symbol.dispose](): void;
186
200
  };
187
201
  Status: typeof Status;
188
202
  Resource: typeof Resource;
@@ -193,6 +207,19 @@ export declare namespace Transaction {
193
207
  type Resource = ResourceType;
194
208
  type ResourceSet = ResourceSetType;
195
209
  type Participant = ParticipantType;
210
+ interface Disposable extends Transaction, AsyncDisposable {
211
+ close(): MaybePromise<void>;
212
+ }
213
+ interface Finalization {
214
+ /**
215
+ * Finish the transaction. If {@link result} is a promise this may result on commit or rollback.
216
+ */
217
+ resolve<T>(result: T): MaybePromise<Awaited<T>>;
218
+ /**
219
+ * Roll back, close the transaction and throw an error.
220
+ */
221
+ reject(cause: unknown): MaybePromise<never>;
222
+ }
196
223
  }
197
224
  export {};
198
225
  //# sourceMappingURL=Transaction.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Transaction.d.ts","sourceRoot":"","sources":["../../../src/transaction/Transaction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IAExC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;IAEtD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAElD;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAEjC;;;;;OAKG;IACH,YAAY,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD;;;;;OAKG;IACH,gBAAgB,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEjD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,SAAS,IAAI,IAAI,CAAC;IAElB;;OAEG;IACH,eAAe,CAAC,GAAG,YAAY,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAEtD;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,EAAE,GAAG,WAAW,GAAG,SAAS,CAAC;IAElD;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY,CAAC;IAEvB;;;;;;;OAOG;IACH,QAAQ,IAAI,YAAY,CAAC;IAEzB;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,KAAK,UAAU,GAAG,MAAM,CAAC;AACzB,KAAK,YAAY,GAAG,QAAQ,CAAC;AAC7B,KAAK,eAAe,GAAG,WAAW,CAAC;AACnC,KAAK,eAAe,GAAG,WAAW,CAAC;AAEnC,eAAO,MAAM,WAAW;IACpB;;;;;;;OAOG;QACC,CAAC,OAAO,MAAM,SAAS,CAAC,WAAW,EAAE,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAY7F,CAAC;AAKF,yBAAiB,WAAW,CAAC;IACzB,KAAY,MAAM,GAAG,UAAU,CAAC;IAEhC,KAAY,QAAQ,GAAG,YAAY,CAAC;IAEpC,KAAY,WAAW,GAAG,eAAe,CAAC;IAE1C,KAAY,WAAW,GAAG,eAAe,CAAC;CAC7C"}
1
+ {"version":3,"file":"Transaction.d.ts","sourceRoot":"","sources":["../../../src/transaction/Transaction.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,WAAW;IACxB;;OAEG;IACH,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IAExC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC;IAElC;;OAEG;IACH,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,SAAS,CAAC;IAEtD;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAElD;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAEjC;;;;;OAKG;IACH,YAAY,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtD;;;;;OAKG;IACH,gBAAgB,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEjD;;;;;;;;;;;;;;;;;;;OAmBG;IACH,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvB;;;;;OAKG;IACH,SAAS,IAAI,IAAI,CAAC;IAElB;;OAEG;IACH,eAAe,CAAC,GAAG,YAAY,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IAEtD;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,EAAE,GAAG,WAAW,GAAG,SAAS,CAAC;IAElD;;;;;;;OAOG;IACH,MAAM,IAAI,YAAY,CAAC;IAEvB;;;;;;;OAOG;IACH,QAAQ,IAAI,YAAY,CAAC;IAEzB;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,KAAK,UAAU,GAAG,MAAM,CAAC;AACzB,KAAK,YAAY,GAAG,QAAQ,CAAC;AAC7B,KAAK,eAAe,GAAG,WAAW,CAAC;AACnC,KAAK,eAAe,GAAG,WAAW,CAAC;AAEnC,eAAO,MAAM,WAAW;IACpB;;;;;;;;;OASG;QACC,CAAC,OAAO,MAAM,SAAS,CAAC,WAAW,EAAE,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC;IAa1F;;;;;;OAMG;cACO,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAYnB,CAAC;AAKF,yBAAiB,WAAW,CAAC;IACzB,KAAY,MAAM,GAAG,UAAU,CAAC;IAEhC,KAAY,QAAQ,GAAG,YAAY,CAAC;IAEpC,KAAY,WAAW,GAAG,eAAe,CAAC;IAE1C,KAAY,WAAW,GAAG,eAAe,CAAC;IAE1C,UAAiB,UAAW,SAAQ,WAAW,EAAE,eAAe;QAC5D,KAAK,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;KAC/B;IAED,UAAiB,YAAY;QACzB;;WAEG;QACH,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAEhD;;WAEG;QACH,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;KAC/C;CACJ"}
@@ -31,7 +31,9 @@ var import_Tx = require("./Tx.js");
31
31
  */
32
32
  const Transaction = {
33
33
  /**
34
- * Perform a transactional operation. This is the only way to obtain a read/write transaction.
34
+ * Perform a transactional operation.
35
+ *
36
+ * This creates a read/write transaction scoped to the life of an optionally async function call.
35
37
  *
36
38
  * The transaction will commit automatically if it is exclusive (write mode) after the actor returns.
37
39
  *
@@ -39,12 +41,29 @@ const Transaction = {
39
41
  * destroyed.
40
42
  */
41
43
  act(via, actor) {
42
- return (0, import_Tx.act)(via, actor);
44
+ const tx = (0, import_Tx.open)(via);
45
+ let result;
46
+ try {
47
+ result = actor(tx);
48
+ } catch (e) {
49
+ return tx.reject(e);
50
+ }
51
+ return tx.resolve(result);
52
+ },
53
+ /**
54
+ * Create a transaction.
55
+ *
56
+ * Transactions must be closed using {@link Finalization#resolve} or {@link Finalization#reject}.
57
+ *
58
+ * When closed the transaction commits automatically if exclusive.
59
+ */
60
+ open(via) {
61
+ return (0, import_Tx.open)(via);
43
62
  },
44
63
  ReadOnly: import_Tx.ReadOnlyTransaction,
45
64
  Status: import_Status.Status,
46
65
  Resource: import_Resource.Resource,
47
66
  [Symbol.toStringTag]: "Transaction"
48
67
  };
49
- Transaction.act = import_Tx.act;
68
+ Transaction.open = import_Tx.open;
50
69
  //# sourceMappingURL=Transaction.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/transaction/Transaction.ts"],
4
- "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAAyB;AAEzB,oBAAuB;AACvB,gBAAyC;AAXzC;AAAA;AAAA;AAAA;AAAA;AA0JO,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvB,IAAO,KAAa,OAAuE;AAEvF,eAAO,eAAI,KAAK,KAAK;AAAA,EACzB;AAAA,EAEA,UAAU;AAAA,EAEV;AAAA,EAEA;AAAA,EAEA,CAAC,OAAO,WAAW,GAAG;AAC1B;AAGA,YAAY,MAAM;",
4
+ "mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,sBAAyB;AAEzB,oBAAuB;AACvB,gBAA0C;AAX1C;AAAA;AAAA;AAAA;AAAA;AA0JO,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWvB,IAAO,KAAa,OAAuE;AACvF,UAAM,SAAK,gBAAK,GAAG;AAEnB,QAAI;AACJ,QAAI;AACA,eAAS,MAAM,EAAE;AAAA,IACrB,SAAS,GAAG;AACR,aAAO,GAAG,OAAO,CAAC;AAAA,IACtB;AAEA,WAAO,GAAG,QAAQ,MAAM;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,KAAK,KAAa;AAEd,eAAO,gBAAK,GAAG;AAAA,EACnB;AAAA,EAEA,UAAU;AAAA,EAEV;AAAA,EAEA;AAAA,EAEA,CAAC,OAAO,WAAW,GAAG;AAC1B;AAGA,YAAY,OAAO;",
5
5
  "names": []
6
6
  }
@@ -11,20 +11,23 @@ import type { Transaction } from "./Transaction.js";
11
11
  /**
12
12
  * This is the only public interface to this file.
13
13
  */
14
- export declare function act<T>(via: string, actor: (transaction: Transaction) => T): T;
14
+ export declare function open(via: string): Transaction & Transaction.Finalization;
15
15
  /**
16
16
  * The concrete implementation of the Transaction interface.
17
17
  */
18
- declare class Tx implements Transaction {
18
+ declare class Tx implements Transaction, Transaction.Finalization {
19
19
  #private;
20
20
  constructor(via: string, readonly?: boolean);
21
- close(): void;
21
+ [Symbol.dispose](): void;
22
22
  get via(): string;
23
23
  get status(): Status;
24
24
  get participants(): Set<Participant>;
25
25
  get resources(): Set<Resource>;
26
26
  get waitingOn(): Iterable<Transaction> | undefined;
27
27
  get isAsync(): boolean;
28
+ /**
29
+ * We set this during async processing. This enables the lock reporting when too much time ellapses.
30
+ */
28
31
  set isAsync(isAsync: true);
29
32
  onShared(listener: () => void, once?: boolean): void;
30
33
  onClose(listener: () => void): void;
@@ -34,8 +37,10 @@ declare class Tx implements Transaction {
34
37
  beginSync(): void;
35
38
  addParticipants(...participants: Participant[]): void;
36
39
  getParticipant(role: {}): Participant | undefined;
37
- commit(): MaybePromise;
40
+ commit(): MaybePromise<void>;
41
+ resolve<T>(result: T): MaybePromise<Awaited<T>>;
38
42
  rollback(): Promise<void> | undefined;
43
+ reject(cause: unknown): MaybePromise<never>;
39
44
  waitFor(others: Set<Transaction>): Promise<void>;
40
45
  toString(): string;
41
46
  treatAsSlow(): void;
@@ -1 +1 @@
1
- {"version":3,"file":"Tx.d.ts","sourceRoot":"","sources":["../../../src/transaction/Tx.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAUpD;;GAEG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,WAAW,KAAK,CAAC,GAAG,CAAC,CA8F7E;AAED;;GAEG;AACH,cAAM,EAAG,YAAW,WAAW;;gBAYf,GAAG,EAAE,MAAM,EAAE,QAAQ,UAAQ;IASzC,KAAK;IASL,IAAI,GAAG,WAEN;IAED,IAAI,MAAM,WAET;IAED,IAAI,YAAY,qBAEf;IAED,IAAI,SAAS,kBAEZ;IAED,IAAI,SAAS,sCAEZ;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,EAOxB;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO;IAW7C,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI;IAatB,YAAY,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE;IAY3C,gBAAgB,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE;IAgBnC,KAAK;IAsBX,SAAS;IAqBT,eAAe,CAAC,GAAG,YAAY,EAAE,WAAW,EAAE;IAyB9C,cAAc,CAAC,IAAI,EAAE,EAAE;IAMvB,MAAM;IAyBN,QAAQ;IAMR,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC;IA6BhC,QAAQ;IAIR,WAAW;CAuWd;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,IAA2B,CAAC"}
1
+ {"version":3,"file":"Tx.d.ts","sourceRoot":"","sources":["../../../src/transaction/Tx.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAUpD;;GAEG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CAAC,YAAY,CAExE;AAED;;GAEG;AACH,cAAM,EAAG,YAAW,WAAW,EAAE,WAAW,CAAC,YAAY;;gBAYzC,GAAG,EAAE,MAAM,EAAE,QAAQ,UAAQ;IASzC,CAAC,MAAM,CAAC,OAAO,CAAC;IAMhB,IAAI,GAAG,WAEN;IAED,IAAI,MAAM,WAET;IAED,IAAI,YAAY,qBAEf;IAED,IAAI,SAAS,kBAEZ;IAED,IAAI,SAAS,sCAEZ;IAED,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,OAAO,EAAE,IAAI,EAOxB;IAED,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,EAAE,IAAI,CAAC,EAAE,OAAO;IAW7C,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI;IAatB,YAAY,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE;IAY3C,gBAAgB,CAAC,GAAG,SAAS,EAAE,QAAQ,EAAE;IAgBnC,KAAK;IAsBX,SAAS;IAqBT,eAAe,CAAC,GAAG,YAAY,EAAE,WAAW,EAAE;IAyB9C,cAAc,CAAC,IAAI,EAAE,EAAE;IAMvB,MAAM;IAeN,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAiC/C,QAAQ;IAMR,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,CAAC,KAAK,CAAC;IAyE3C,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,WAAW,CAAC;IA6BhC,QAAQ;IAIR,WAAW;CAuYd;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,IAA2B,CAAC"}
@@ -19,13 +19,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
19
19
  var Tx_exports = {};
20
20
  __export(Tx_exports, {
21
21
  ReadOnlyTransaction: () => ReadOnlyTransaction,
22
- act: () => act
22
+ open: () => open
23
23
  });
24
24
  module.exports = __toCommonJS(Tx_exports);
25
25
  var import_Diagnostic = require("#log/Diagnostic.js");
26
26
  var import_Logger = require("#log/Logger.js");
27
27
  var import_MatterError = require("#MatterError.js");
28
28
  var import_Time = require("#time/Time.js");
29
+ var import_Error = require("#util/Error.js");
29
30
  var import_Observable = require("#util/Observable.js");
30
31
  var import_Promises = require("#util/Promises.js");
31
32
  var import_String = require("#util/String.js");
@@ -40,74 +41,8 @@ var import_Status = require("./Status.js");
40
41
  const logger = import_Logger.Logger.get("Transaction");
41
42
  const MAX_PRECOMMIT_CYCLES = 5;
42
43
  const MAX_CHAINED_COMMITS = 5;
43
- function act(via, actor) {
44
- const tx = new Tx(via);
45
- let commits = 0;
46
- function commitTransaction(finalResult) {
47
- commits++;
48
- if (commits > MAX_CHAINED_COMMITS) {
49
- throw new import_errors.TransactionFlowError(
50
- `Transaction commits have cascaded ${MAX_CHAINED_COMMITS} times which likely indicates an infinite loop`
51
- );
52
- }
53
- const result = tx.commit();
54
- if (import_Promises.MaybePromise.is(result)) {
55
- return result.then(() => {
56
- if (tx.status === import_Status.Status.Exclusive) {
57
- return commitTransaction(finalResult);
58
- }
59
- return finalResult;
60
- });
61
- } else if (tx.status === import_Status.Status.Exclusive) {
62
- return commitTransaction(finalResult);
63
- }
64
- return finalResult;
65
- }
66
- const handleTransactionError = (error) => {
67
- if (commits) {
68
- throw error;
69
- }
70
- logger.error("Rolling back", tx.via, "due to error:", import_Diagnostic.Diagnostic.weak(error?.message || `${error}`));
71
- try {
72
- const result = tx.rollback();
73
- if (import_Promises.MaybePromise.is(result)) {
74
- return Promise.resolve(result).catch((error2) => {
75
- if (error2 !== error) {
76
- logger.error("Secondary error in", tx.via, "rollback:", error2);
77
- }
78
- throw error;
79
- });
80
- }
81
- } catch (error2) {
82
- if (error2 !== error) {
83
- logger.error("Secondary error in", tx.via, "rollback:", error2);
84
- }
85
- }
86
- throw error;
87
- };
88
- const closeTransaction = tx.close.bind(tx);
89
- let isAsync = false;
90
- try {
91
- const actorResult = actor(tx);
92
- if (import_Promises.MaybePromise.is(actorResult)) {
93
- isAsync = tx.isAsync = true;
94
- return Promise.resolve(actorResult).then(commitTransaction, handleTransactionError).finally(closeTransaction);
95
- }
96
- const commitResult = commitTransaction(actorResult);
97
- if (import_Promises.MaybePromise.is(commitResult)) {
98
- isAsync = true;
99
- return Promise.resolve(commitResult).catch(handleTransactionError).finally(closeTransaction);
100
- }
101
- return commitResult;
102
- } catch (e) {
103
- const result = handleTransactionError(e);
104
- isAsync = true;
105
- return Promise.resolve(result).finally(closeTransaction);
106
- } finally {
107
- if (!isAsync) {
108
- tx.close();
109
- }
110
- }
44
+ function open(via) {
45
+ return new Tx(via);
111
46
  }
112
47
  class Tx {
113
48
  #participants = /* @__PURE__ */ new Set();
@@ -128,12 +63,9 @@ class Tx {
128
63
  this.#status = import_Status.Status.Shared;
129
64
  }
130
65
  }
131
- close() {
132
- Monitor.delete(this);
66
+ [Symbol.dispose]() {
67
+ this.#reset("dropped");
133
68
  this.#status = import_Status.Status.Destroyed;
134
- this.#resources.clear();
135
- this.#roles.clear();
136
- this.#participants.clear();
137
69
  this.#closed?.emit();
138
70
  }
139
71
  get via() {
@@ -154,6 +86,9 @@ class Tx {
154
86
  get isAsync() {
155
87
  return this.#isAsync;
156
88
  }
89
+ /**
90
+ * We set this during async processing. This enables the lock reporting when too much time ellapses.
91
+ */
157
92
  set isAsync(isAsync) {
158
93
  if (!this.#isAsync) {
159
94
  this.#locksChanged(this.#resources);
@@ -263,28 +198,97 @@ class Tx {
263
198
  return this.#roles.get(role);
264
199
  }
265
200
  commit() {
266
- this.#assertAvailable();
267
- if (this.#status === import_Status.Status.Shared) {
201
+ if (this.status === import_Status.Status.Shared) {
268
202
  return this.rollback();
269
203
  }
270
- const performCommit = () => {
271
- const participants = [...this.#participants];
272
- const result2 = this.#finalize(import_Status.Status.CommittingPhaseOne, "committed", this.#executeCommit.bind(this));
273
- if (import_Promises.MaybePromise.is(result2)) {
274
- return result2.then(() => this.#executePostCommit(participants));
275
- }
276
- return this.#executePostCommit(participants);
277
- };
278
- const result = this.#executePreCommit();
204
+ this.#assertAvailable();
205
+ const result = this.#executeCommitCycle(0);
206
+ if (result) {
207
+ this.isAsync = true;
208
+ }
209
+ return result;
210
+ }
211
+ resolve(result) {
279
212
  if (import_Promises.MaybePromise.is(result)) {
280
- return result.then(performCommit);
213
+ this.isAsync = true;
214
+ return result.then(this.resolve.bind(this), this.reject.bind(this));
215
+ }
216
+ let promise;
217
+ try {
218
+ promise = this.commit();
219
+ } catch (e) {
220
+ return this.reject(e);
281
221
  }
282
- return performCommit();
222
+ if (import_Promises.MaybePromise.is(promise)) {
223
+ this.isAsync = true;
224
+ return Promise.resolve(promise).then(() => {
225
+ this[Symbol.dispose]();
226
+ return result;
227
+ }, this.reject.bind(this)).finally(this[Symbol.dispose].bind(this));
228
+ }
229
+ this[Symbol.dispose]();
230
+ return result;
283
231
  }
284
232
  rollback() {
285
233
  this.#assertAvailable();
286
234
  return this.#finalize(import_Status.Status.RollingBack, "rolled back", () => this.#executeRollback());
287
235
  }
236
+ reject(cause) {
237
+ if (this.#status === import_Status.Status.Shared) {
238
+ this.#reset("released");
239
+ throw cause;
240
+ }
241
+ logger.error("Rolling back", this.via, "due to error:", import_Diagnostic.Diagnostic.weak((0, import_Error.asError)(cause).message));
242
+ try {
243
+ const result = this.rollback();
244
+ if (import_Promises.MaybePromise.is(result)) {
245
+ return Promise.resolve(result).catch((cause2) => {
246
+ if (cause2 === cause) {
247
+ return;
248
+ }
249
+ logger.error("Secondary error in", this.via, "rollback:", cause2);
250
+ }).finally(() => {
251
+ this[Symbol.dispose]();
252
+ throw cause;
253
+ });
254
+ }
255
+ } catch (cause2) {
256
+ if (cause2 !== cause) {
257
+ logger.error("Secondary error in", this.via, "rollback:", cause2);
258
+ }
259
+ }
260
+ this[Symbol.dispose]();
261
+ throw cause;
262
+ }
263
+ /**
264
+ * Execute commit logic for a single commit cycle.
265
+ *
266
+ * A "cycle" performs all commit logic and normally brings us back to shared state. But we allow post-commit
267
+ * handlers to re-enter exclusive state. If that happens, we trigger another commit cycle.
268
+ */
269
+ #executeCommitCycle(count) {
270
+ count++;
271
+ if (count > MAX_CHAINED_COMMITS) {
272
+ throw new import_errors.TransactionFlowError(
273
+ `Transaction commits have cascaded ${count} times which likely indicates an infinite loop`
274
+ );
275
+ }
276
+ let result = this.#createPreCommitExecutor()();
277
+ if (import_Promises.MaybePromise.is(result)) {
278
+ result = result.then(this.#executeCommit.bind(this));
279
+ } else {
280
+ result = this.#executeCommit();
281
+ }
282
+ if (import_Promises.MaybePromise.is(result)) {
283
+ return result.then(() => {
284
+ if (this.#status === import_Status.Status.Exclusive) {
285
+ return this.#executeCommitCycle(count);
286
+ }
287
+ });
288
+ } else if (this.#status === import_Status.Status.Exclusive) {
289
+ return this.#executeCommitCycle(count);
290
+ }
291
+ }
288
292
  waitFor(others) {
289
293
  this.#assertAvailable();
290
294
  if (this.waitingOn) {
@@ -330,34 +334,39 @@ class Tx {
330
334
  `Illegal attempt to enter status ${status} when transaction is ${this.#status}`
331
335
  );
332
336
  }
333
- const cleanup = () => {
334
- const set = new import_ResourceSet.ResourceSet(this, this.#resources);
335
- const unlocked = set.releaseLocks();
336
- this.#locksChanged(unlocked, `${why} and unlocked`);
337
- Monitor.delete(this);
338
- this.#reportingLocks = false;
339
- this.#participants.clear();
340
- this.#status = import_Status.Status.Shared;
341
- this.#shared?.emit();
342
- };
343
337
  let isAsync = false;
344
338
  try {
345
339
  this.#status = status;
346
340
  const result = finalizer();
347
341
  if (import_Promises.MaybePromise.is(result)) {
348
342
  isAsync = true;
349
- return Promise.resolve(result).finally(cleanup);
343
+ return Promise.resolve(result).finally(() => this.#reset(why));
350
344
  }
351
345
  } finally {
352
346
  if (!isAsync) {
353
- cleanup();
347
+ this.#reset(why);
354
348
  }
355
349
  }
356
350
  }
351
+ /**
352
+ * Reset state to shared with no resources or participants.
353
+ */
354
+ #reset(why) {
355
+ const set = new import_ResourceSet.ResourceSet(this, this.#resources);
356
+ const unlocked = set.releaseLocks();
357
+ this.#locksChanged(unlocked, `${why} and unlocked`);
358
+ this.#resources.clear();
359
+ Monitor.delete(this);
360
+ this.#reportingLocks = false;
361
+ this.#participants.clear();
362
+ this.#roles.clear();
363
+ this.#status = import_Status.Status.Shared;
364
+ this.#shared?.emit();
365
+ }
357
366
  /**
358
367
  * Iteratively execute pre-commit until all participants "settle" and report no possible mutation.
359
368
  */
360
- #executePreCommit() {
369
+ #createPreCommitExecutor() {
361
370
  let mayHaveMutated = false;
362
371
  let abortedDueToError = false;
363
372
  let iterator = this.participants[Symbol.iterator]();
@@ -389,7 +398,7 @@ class Tx {
389
398
  mayHaveMutated = false;
390
399
  iterator = this.participants[Symbol.iterator]();
391
400
  };
392
- const nextPreCommit = (previousResult) => {
401
+ const executePreCommit = (previousResult) => {
393
402
  if (abortedDueToError) {
394
403
  return;
395
404
  }
@@ -416,7 +425,7 @@ class Tx {
416
425
  try {
417
426
  const result = participant.preCommit?.();
418
427
  if (import_Promises.MaybePromise.is(result)) {
419
- return Promise.resolve(result).catch(handleError).then(nextPreCommit);
428
+ return Promise.resolve(result).catch(handleError).then(executePreCommit);
420
429
  }
421
430
  if (result) {
422
431
  mayHaveMutated = true;
@@ -426,17 +435,26 @@ class Tx {
426
435
  }
427
436
  }
428
437
  };
429
- return nextPreCommit();
438
+ return executePreCommit;
430
439
  }
431
440
  /**
432
- * Commit logic passed to #finalize.
441
+ * Handle actual commit and post-commit.
433
442
  */
434
443
  #executeCommit() {
435
- const result = this.#executeCommit1();
444
+ const participants = [...this.#participants];
445
+ const executeCommit = () => {
446
+ const result2 = this.#executeCommit1();
447
+ if (import_Promises.MaybePromise.is(result2)) {
448
+ return Promise.resolve(result2).then(this.#executeCommit2.bind(this));
449
+ }
450
+ return this.#executeCommit2();
451
+ };
452
+ const result = this.#finalize(import_Status.Status.CommittingPhaseOne, "committed", executeCommit);
453
+ const executePostCommit = this.#createPostCommitExecutor(participants);
436
454
  if (import_Promises.MaybePromise.is(result)) {
437
- return Promise.resolve(result).then(this.#executeCommit2.bind(this));
455
+ return result.then(executePostCommit);
438
456
  }
439
- return this.#executeCommit2();
457
+ return executePostCommit();
440
458
  }
441
459
  #executeCommit1() {
442
460
  let needRollback = false;
@@ -506,23 +524,35 @@ class Tx {
506
524
  throwIfErrored(errored, "in commit phase 2");
507
525
  }
508
526
  }
509
- #executePostCommit(participants) {
510
- const participantIterator = participants[Symbol.iterator]();
511
- const postCommitNextParticipant = () => {
512
- const next = participantIterator.next();
513
- if (next.done) {
514
- return;
515
- }
516
- const participant = next.value;
517
- return import_Promises.MaybePromise.then(
518
- () => participant.postCommit?.(),
519
- () => postCommitNextParticipant(),
520
- (error) => {
521
- logger.error(`Error post-commit of ${participant}:`, error);
527
+ /**
528
+ * Execute post-commit phase.
529
+ *
530
+ * We notify each participant sequentially. If a participant throws, we log the error and move on to the next
531
+ * participant.
532
+ */
533
+ #createPostCommitExecutor(participants) {
534
+ let i = 0;
535
+ const executePostCommit = () => {
536
+ for (; i < participants.length; i++) {
537
+ let reportParticipantError2 = function(e) {
538
+ logger.error(`Error post-commit of ${participant}:`, e);
539
+ };
540
+ var reportParticipantError = reportParticipantError2;
541
+ const participant = participants[i];
542
+ try {
543
+ const promise = participant.postCommit?.();
544
+ if (import_Promises.MaybePromise.is(promise)) {
545
+ return Promise.resolve(promise).then(executePostCommit, (e) => {
546
+ reportParticipantError2(e);
547
+ executePostCommit();
548
+ });
549
+ }
550
+ } catch (e) {
551
+ reportParticipantError2(e);
522
552
  }
523
- );
553
+ }
524
554
  };
525
- return postCommitNextParticipant();
555
+ return executePostCommit;
526
556
  }
527
557
  /**
528
558
  * Rollback logic passed to #finish.