@matter/general 0.13.1-alpha.0-20250520-d699cd56d → 0.14.0-alpha.0-20250524-51a7e1721

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 +49 -22
  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 +49 -22
  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
@@ -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,18 +144,25 @@ 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
- "__#15458@#participants": Set<Participant>;
147
- "__#15458@#roles": Map<{}, Participant>;
148
- "__#15458@#resources": Set<Resource>;
149
- "__#15458@#status": Status;
150
- "__#15458@#waitingOn"?: Iterable<Transaction>;
151
- "__#15458@#via": string;
152
- "__#15458@#shared"?: import("../index.js").Observable<[]>;
153
- "__#15458@#closed"?: import("../index.js").Observable<[]>;
154
- "__#15458@#isAsync": boolean;
155
- "__#15458@#reportingLocks": boolean;
156
- close(): void;
156
+ "__#15463@#participants": Set<Participant>;
157
+ "__#15463@#roles": Map<{}, Participant>;
158
+ "__#15463@#resources": Set<Resource>;
159
+ "__#15463@#status": Status;
160
+ "__#15463@#waitingOn"?: Iterable<Transaction>;
161
+ "__#15463@#via": string;
162
+ "__#15463@#shared"?: import("../index.js").Observable<[]>;
163
+ "__#15463@#closed"?: import("../index.js").Observable<[]>;
164
+ "__#15463@#isAsync": boolean;
165
+ "__#15463@#reportingLocks": boolean;
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
+ "__#15463@#executeCommitCycle"(count: number): MaybePromise<void>;
174
186
  waitFor(others: Set<Transaction>): Promise<void>;
175
187
  toString(): string;
176
188
  treatAsSlow(): void;
177
- "__#15458@#finalize"(status: Status, why: string, finalizer: () => MaybePromise): Promise<void> | undefined;
178
- "__#15458@#executePreCommit"(): MaybePromise<void>;
179
- "__#15458@#executeCommit"(): MaybePromise;
180
- "__#15458@#executeCommit1"(): MaybePromise;
181
- "__#15458@#executeCommit2"(): Promise<void> | undefined;
182
- "__#15458@#executePostCommit"(participants: Participant[]): MaybePromise;
183
- "__#15458@#executeRollback"(): Promise<void> | undefined;
184
- "__#15458@#locksChanged"(resources: Set<Resource>, how?: string): void;
185
- "__#15458@#assertAvailable"(): void;
189
+ "__#15463@#finalize"(status: Status, why: string, finalizer: () => MaybePromise): Promise<void> | undefined;
190
+ "__#15463@#reset"(why: string): void;
191
+ "__#15463@#createPreCommitExecutor"(): () => MaybePromise<void>;
192
+ "__#15463@#executeCommit"(): MaybePromise;
193
+ "__#15463@#executeCommit1"(): MaybePromise;
194
+ "__#15463@#executeCommit2"(): Promise<void> | undefined;
195
+ "__#15463@#createPostCommitExecutor"(participants: Participant[]): () => MaybePromise;
196
+ "__#15463@#executeRollback"(): Promise<void> | undefined;
197
+ "__#15463@#locksChanged"(resources: Set<Resource>, how?: string): void;
198
+ "__#15463@#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":"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"}
@@ -5,10 +5,12 @@
5
5
  */
6
6
  import { Resource } from "./Resource.js";
7
7
  import { Status } from "./Status.js";
8
- import { ReadOnlyTransaction, act } from "./Tx.js";
8
+ import { ReadOnlyTransaction, open } from "./Tx.js";
9
9
  const Transaction = {
10
10
  /**
11
- * Perform a transactional operation. This is the only way to obtain a read/write transaction.
11
+ * Perform a transactional operation.
12
+ *
13
+ * This creates a read/write transaction scoped to the life of an optionally async function call.
12
14
  *
13
15
  * The transaction will commit automatically if it is exclusive (write mode) after the actor returns.
14
16
  *
@@ -16,14 +18,31 @@ const Transaction = {
16
18
  * destroyed.
17
19
  */
18
20
  act(via, actor) {
19
- return act(via, actor);
21
+ const tx = open(via);
22
+ let result;
23
+ try {
24
+ result = actor(tx);
25
+ } catch (e) {
26
+ return tx.reject(e);
27
+ }
28
+ return tx.resolve(result);
29
+ },
30
+ /**
31
+ * Create a transaction.
32
+ *
33
+ * Transactions must be closed using {@link Finalization#resolve} or {@link Finalization#reject}.
34
+ *
35
+ * When closed the transaction commits automatically if exclusive.
36
+ */
37
+ open(via) {
38
+ return open(via);
20
39
  },
21
40
  ReadOnly: ReadOnlyTransaction,
22
41
  Status,
23
42
  Resource,
24
43
  [Symbol.toStringTag]: "Transaction"
25
44
  };
26
- Transaction.act = act;
45
+ Transaction.open = open;
27
46
  export {
28
47
  Transaction
29
48
  };
@@ -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,SAAS,gBAAgB;AAEzB,SAAS,cAAc;AACvB,SAAS,qBAAqB,WAAW;AA+IlC,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvB,IAAO,KAAa,OAAuE;AAEvF,WAAO,IAAI,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,SAAS,gBAAgB;AAEzB,SAAS,cAAc;AACvB,SAAS,qBAAqB,YAAY;AA+InC,MAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWvB,IAAO,KAAa,OAAuE;AACvF,UAAM,KAAK,KAAK,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,WAAO,KAAK,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"}
@@ -7,6 +7,7 @@ import { Diagnostic } from "#log/Diagnostic.js";
7
7
  import { Logger } from "#log/Logger.js";
8
8
  import { ImplementationError, ReadOnlyError } from "#MatterError.js";
9
9
  import { Time } from "#time/Time.js";
10
+ import { asError } from "#util/Error.js";
10
11
  import { Observable } from "#util/Observable.js";
11
12
  import { MaybePromise } from "#util/Promises.js";
12
13
  import { describeList } from "#util/String.js";
@@ -16,74 +17,8 @@ import { Status } from "./Status.js";
16
17
  const logger = Logger.get("Transaction");
17
18
  const MAX_PRECOMMIT_CYCLES = 5;
18
19
  const MAX_CHAINED_COMMITS = 5;
19
- function act(via, actor) {
20
- const tx = new Tx(via);
21
- let commits = 0;
22
- function commitTransaction(finalResult) {
23
- commits++;
24
- if (commits > MAX_CHAINED_COMMITS) {
25
- throw new TransactionFlowError(
26
- `Transaction commits have cascaded ${MAX_CHAINED_COMMITS} times which likely indicates an infinite loop`
27
- );
28
- }
29
- const result = tx.commit();
30
- if (MaybePromise.is(result)) {
31
- return result.then(() => {
32
- if (tx.status === Status.Exclusive) {
33
- return commitTransaction(finalResult);
34
- }
35
- return finalResult;
36
- });
37
- } else if (tx.status === Status.Exclusive) {
38
- return commitTransaction(finalResult);
39
- }
40
- return finalResult;
41
- }
42
- const handleTransactionError = (error) => {
43
- if (commits) {
44
- throw error;
45
- }
46
- logger.error("Rolling back", tx.via, "due to error:", Diagnostic.weak(error?.message || `${error}`));
47
- try {
48
- const result = tx.rollback();
49
- if (MaybePromise.is(result)) {
50
- return Promise.resolve(result).catch((error2) => {
51
- if (error2 !== error) {
52
- logger.error("Secondary error in", tx.via, "rollback:", error2);
53
- }
54
- throw error;
55
- });
56
- }
57
- } catch (error2) {
58
- if (error2 !== error) {
59
- logger.error("Secondary error in", tx.via, "rollback:", error2);
60
- }
61
- }
62
- throw error;
63
- };
64
- const closeTransaction = tx.close.bind(tx);
65
- let isAsync = false;
66
- try {
67
- const actorResult = actor(tx);
68
- if (MaybePromise.is(actorResult)) {
69
- isAsync = tx.isAsync = true;
70
- return Promise.resolve(actorResult).then(commitTransaction, handleTransactionError).finally(closeTransaction);
71
- }
72
- const commitResult = commitTransaction(actorResult);
73
- if (MaybePromise.is(commitResult)) {
74
- isAsync = true;
75
- return Promise.resolve(commitResult).catch(handleTransactionError).finally(closeTransaction);
76
- }
77
- return commitResult;
78
- } catch (e) {
79
- const result = handleTransactionError(e);
80
- isAsync = true;
81
- return Promise.resolve(result).finally(closeTransaction);
82
- } finally {
83
- if (!isAsync) {
84
- tx.close();
85
- }
86
- }
20
+ function open(via) {
21
+ return new Tx(via);
87
22
  }
88
23
  class Tx {
89
24
  #participants = /* @__PURE__ */ new Set();
@@ -104,12 +39,9 @@ class Tx {
104
39
  this.#status = Status.Shared;
105
40
  }
106
41
  }
107
- close() {
108
- Monitor.delete(this);
42
+ [Symbol.dispose]() {
43
+ this.#reset("dropped");
109
44
  this.#status = Status.Destroyed;
110
- this.#resources.clear();
111
- this.#roles.clear();
112
- this.#participants.clear();
113
45
  this.#closed?.emit();
114
46
  }
115
47
  get via() {
@@ -130,6 +62,9 @@ class Tx {
130
62
  get isAsync() {
131
63
  return this.#isAsync;
132
64
  }
65
+ /**
66
+ * We set this during async processing. This enables the lock reporting when too much time ellapses.
67
+ */
133
68
  set isAsync(isAsync) {
134
69
  if (!this.#isAsync) {
135
70
  this.#locksChanged(this.#resources);
@@ -239,28 +174,97 @@ class Tx {
239
174
  return this.#roles.get(role);
240
175
  }
241
176
  commit() {
242
- this.#assertAvailable();
243
- if (this.#status === Status.Shared) {
177
+ if (this.status === Status.Shared) {
244
178
  return this.rollback();
245
179
  }
246
- const performCommit = () => {
247
- const participants = [...this.#participants];
248
- const result2 = this.#finalize(Status.CommittingPhaseOne, "committed", this.#executeCommit.bind(this));
249
- if (MaybePromise.is(result2)) {
250
- return result2.then(() => this.#executePostCommit(participants));
251
- }
252
- return this.#executePostCommit(participants);
253
- };
254
- const result = this.#executePreCommit();
180
+ this.#assertAvailable();
181
+ const result = this.#executeCommitCycle(0);
182
+ if (result) {
183
+ this.isAsync = true;
184
+ }
185
+ return result;
186
+ }
187
+ resolve(result) {
255
188
  if (MaybePromise.is(result)) {
256
- return result.then(performCommit);
189
+ this.isAsync = true;
190
+ return result.then(this.resolve.bind(this), this.reject.bind(this));
191
+ }
192
+ let promise;
193
+ try {
194
+ promise = this.commit();
195
+ } catch (e) {
196
+ return this.reject(e);
257
197
  }
258
- return performCommit();
198
+ if (MaybePromise.is(promise)) {
199
+ this.isAsync = true;
200
+ return Promise.resolve(promise).then(() => {
201
+ this[Symbol.dispose]();
202
+ return result;
203
+ }, this.reject.bind(this)).finally(this[Symbol.dispose].bind(this));
204
+ }
205
+ this[Symbol.dispose]();
206
+ return result;
259
207
  }
260
208
  rollback() {
261
209
  this.#assertAvailable();
262
210
  return this.#finalize(Status.RollingBack, "rolled back", () => this.#executeRollback());
263
211
  }
212
+ reject(cause) {
213
+ if (this.#status === Status.Shared) {
214
+ this.#reset("released");
215
+ throw cause;
216
+ }
217
+ logger.error("Rolling back", this.via, "due to error:", Diagnostic.weak(asError(cause).message));
218
+ try {
219
+ const result = this.rollback();
220
+ if (MaybePromise.is(result)) {
221
+ return Promise.resolve(result).catch((cause2) => {
222
+ if (cause2 === cause) {
223
+ return;
224
+ }
225
+ logger.error("Secondary error in", this.via, "rollback:", cause2);
226
+ }).finally(() => {
227
+ this[Symbol.dispose]();
228
+ throw cause;
229
+ });
230
+ }
231
+ } catch (cause2) {
232
+ if (cause2 !== cause) {
233
+ logger.error("Secondary error in", this.via, "rollback:", cause2);
234
+ }
235
+ }
236
+ this[Symbol.dispose]();
237
+ throw cause;
238
+ }
239
+ /**
240
+ * Execute commit logic for a single commit cycle.
241
+ *
242
+ * A "cycle" performs all commit logic and normally brings us back to shared state. But we allow post-commit
243
+ * handlers to re-enter exclusive state. If that happens, we trigger another commit cycle.
244
+ */
245
+ #executeCommitCycle(count) {
246
+ count++;
247
+ if (count > MAX_CHAINED_COMMITS) {
248
+ throw new TransactionFlowError(
249
+ `Transaction commits have cascaded ${count} times which likely indicates an infinite loop`
250
+ );
251
+ }
252
+ let result = this.#createPreCommitExecutor()();
253
+ if (MaybePromise.is(result)) {
254
+ result = result.then(this.#executeCommit.bind(this));
255
+ } else {
256
+ result = this.#executeCommit();
257
+ }
258
+ if (MaybePromise.is(result)) {
259
+ return result.then(() => {
260
+ if (this.#status === Status.Exclusive) {
261
+ return this.#executeCommitCycle(count);
262
+ }
263
+ });
264
+ } else if (this.#status === Status.Exclusive) {
265
+ return this.#executeCommitCycle(count);
266
+ }
267
+ }
264
268
  waitFor(others) {
265
269
  this.#assertAvailable();
266
270
  if (this.waitingOn) {
@@ -306,34 +310,39 @@ class Tx {
306
310
  `Illegal attempt to enter status ${status} when transaction is ${this.#status}`
307
311
  );
308
312
  }
309
- const cleanup = () => {
310
- const set = new ResourceSet(this, this.#resources);
311
- const unlocked = set.releaseLocks();
312
- this.#locksChanged(unlocked, `${why} and unlocked`);
313
- Monitor.delete(this);
314
- this.#reportingLocks = false;
315
- this.#participants.clear();
316
- this.#status = Status.Shared;
317
- this.#shared?.emit();
318
- };
319
313
  let isAsync = false;
320
314
  try {
321
315
  this.#status = status;
322
316
  const result = finalizer();
323
317
  if (MaybePromise.is(result)) {
324
318
  isAsync = true;
325
- return Promise.resolve(result).finally(cleanup);
319
+ return Promise.resolve(result).finally(() => this.#reset(why));
326
320
  }
327
321
  } finally {
328
322
  if (!isAsync) {
329
- cleanup();
323
+ this.#reset(why);
330
324
  }
331
325
  }
332
326
  }
327
+ /**
328
+ * Reset state to shared with no resources or participants.
329
+ */
330
+ #reset(why) {
331
+ const set = new ResourceSet(this, this.#resources);
332
+ const unlocked = set.releaseLocks();
333
+ this.#locksChanged(unlocked, `${why} and unlocked`);
334
+ this.#resources.clear();
335
+ Monitor.delete(this);
336
+ this.#reportingLocks = false;
337
+ this.#participants.clear();
338
+ this.#roles.clear();
339
+ this.#status = Status.Shared;
340
+ this.#shared?.emit();
341
+ }
333
342
  /**
334
343
  * Iteratively execute pre-commit until all participants "settle" and report no possible mutation.
335
344
  */
336
- #executePreCommit() {
345
+ #createPreCommitExecutor() {
337
346
  let mayHaveMutated = false;
338
347
  let abortedDueToError = false;
339
348
  let iterator = this.participants[Symbol.iterator]();
@@ -365,7 +374,7 @@ class Tx {
365
374
  mayHaveMutated = false;
366
375
  iterator = this.participants[Symbol.iterator]();
367
376
  };
368
- const nextPreCommit = (previousResult) => {
377
+ const executePreCommit = (previousResult) => {
369
378
  if (abortedDueToError) {
370
379
  return;
371
380
  }
@@ -392,7 +401,7 @@ class Tx {
392
401
  try {
393
402
  const result = participant.preCommit?.();
394
403
  if (MaybePromise.is(result)) {
395
- return Promise.resolve(result).catch(handleError).then(nextPreCommit);
404
+ return Promise.resolve(result).catch(handleError).then(executePreCommit);
396
405
  }
397
406
  if (result) {
398
407
  mayHaveMutated = true;
@@ -402,17 +411,26 @@ class Tx {
402
411
  }
403
412
  }
404
413
  };
405
- return nextPreCommit();
414
+ return executePreCommit;
406
415
  }
407
416
  /**
408
- * Commit logic passed to #finalize.
417
+ * Handle actual commit and post-commit.
409
418
  */
410
419
  #executeCommit() {
411
- const result = this.#executeCommit1();
420
+ const participants = [...this.#participants];
421
+ const executeCommit = () => {
422
+ const result2 = this.#executeCommit1();
423
+ if (MaybePromise.is(result2)) {
424
+ return Promise.resolve(result2).then(this.#executeCommit2.bind(this));
425
+ }
426
+ return this.#executeCommit2();
427
+ };
428
+ const result = this.#finalize(Status.CommittingPhaseOne, "committed", executeCommit);
429
+ const executePostCommit = this.#createPostCommitExecutor(participants);
412
430
  if (MaybePromise.is(result)) {
413
- return Promise.resolve(result).then(this.#executeCommit2.bind(this));
431
+ return result.then(executePostCommit);
414
432
  }
415
- return this.#executeCommit2();
433
+ return executePostCommit();
416
434
  }
417
435
  #executeCommit1() {
418
436
  let needRollback = false;
@@ -482,23 +500,35 @@ class Tx {
482
500
  throwIfErrored(errored, "in commit phase 2");
483
501
  }
484
502
  }
485
- #executePostCommit(participants) {
486
- const participantIterator = participants[Symbol.iterator]();
487
- const postCommitNextParticipant = () => {
488
- const next = participantIterator.next();
489
- if (next.done) {
490
- return;
491
- }
492
- const participant = next.value;
493
- return MaybePromise.then(
494
- () => participant.postCommit?.(),
495
- () => postCommitNextParticipant(),
496
- (error) => {
497
- logger.error(`Error post-commit of ${participant}:`, error);
503
+ /**
504
+ * Execute post-commit phase.
505
+ *
506
+ * We notify each participant sequentially. If a participant throws, we log the error and move on to the next
507
+ * participant.
508
+ */
509
+ #createPostCommitExecutor(participants) {
510
+ let i = 0;
511
+ const executePostCommit = () => {
512
+ for (; i < participants.length; i++) {
513
+ let reportParticipantError2 = function(e) {
514
+ logger.error(`Error post-commit of ${participant}:`, e);
515
+ };
516
+ var reportParticipantError = reportParticipantError2;
517
+ const participant = participants[i];
518
+ try {
519
+ const promise = participant.postCommit?.();
520
+ if (MaybePromise.is(promise)) {
521
+ return Promise.resolve(promise).then(executePostCommit, (e) => {
522
+ reportParticipantError2(e);
523
+ executePostCommit();
524
+ });
525
+ }
526
+ } catch (e) {
527
+ reportParticipantError2(e);
498
528
  }
499
- );
529
+ }
500
530
  };
501
- return postCommitNextParticipant();
531
+ return executePostCommit;
502
532
  }
503
533
  /**
504
534
  * Rollback logic passed to #finish.
@@ -622,6 +652,6 @@ const Monitor = /* @__PURE__ */ function() {
622
652
  }();
623
653
  export {
624
654
  ReadOnlyTransaction,
625
- act
655
+ open
626
656
  };
627
657
  //# sourceMappingURL=Tx.js.map