edinburgh 0.6.0 → 0.6.1
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/README.md +38 -35
- package/build/src/edinburgh.d.ts +3 -0
- package/build/src/edinburgh.js +25 -18
- package/build/src/edinburgh.js.map +1 -1
- package/package.json +2 -2
- package/skill/setOnSaveCallback.md +3 -0
- package/src/edinburgh.ts +27 -18
package/README.md
CHANGED
|
@@ -553,7 +553,7 @@ await E.transact(() => {
|
|
|
553
553
|
});
|
|
554
554
|
```
|
|
555
555
|
|
|
556
|
-
### setMaxRetryCount · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
556
|
+
### setMaxRetryCount · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L232)
|
|
557
557
|
|
|
558
558
|
Set the maximum number of retries for a transaction in case of conflicts.
|
|
559
559
|
The default value is 6. Setting it to 0 will disable retries and cause transactions to fail immediately on conflict.
|
|
@@ -564,7 +564,7 @@ The default value is 6. Setting it to 0 will disable retries and cause transacti
|
|
|
564
564
|
|
|
565
565
|
- `count: number` - The maximum number of retries for a transaction.
|
|
566
566
|
|
|
567
|
-
### setOnSaveCallback · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
567
|
+
### setOnSaveCallback · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L249)
|
|
568
568
|
|
|
569
569
|
Set a callback function to be called after a model is saved and committed.
|
|
570
570
|
|
|
@@ -577,11 +577,14 @@ Set a callback function to be called after a model is saved and committed.
|
|
|
577
577
|
- A sequential number. Higher numbers have been committed after lower numbers.
|
|
578
578
|
- A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
579
579
|
|
|
580
|
-
|
|
580
|
+
The callback is called within a new transaction context, allowing lazy-loads to happen. However, any
|
|
581
|
+
changes made to Edinburgh models will not be saved.
|
|
582
|
+
|
|
583
|
+
### Model · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
581
584
|
|
|
582
585
|
**Type:** `typeof ModelBase`
|
|
583
586
|
|
|
584
|
-
### ModelClass · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
587
|
+
### ModelClass · [class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
585
588
|
|
|
586
589
|
Runtime base constructor for model classes returned by `defineModel()`.
|
|
587
590
|
|
|
@@ -598,7 +601,7 @@ Useful when accepting or storing arbitrary registered model classes.
|
|
|
598
601
|
|
|
599
602
|
**Type:** `ModelClass<new () => any, readonly any[], any, any>`
|
|
600
603
|
|
|
601
|
-
### ModelBase · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
604
|
+
### ModelBase · [abstract class](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
602
605
|
|
|
603
606
|
Base class for all database models in the Edinburgh ORM.
|
|
604
607
|
|
|
@@ -651,7 +654,7 @@ const User = E.defineModel("User", class {
|
|
|
651
654
|
type User = InstanceType<typeof User>;
|
|
652
655
|
```
|
|
653
656
|
|
|
654
|
-
#### ModelBase.migrate · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
657
|
+
#### ModelBase.migrate · [static method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
655
658
|
|
|
656
659
|
Optional migration function called when deserializing rows written with an older schema version.
|
|
657
660
|
Receives a plain record with all fields and should mutate it in-place to match the current schema.
|
|
@@ -678,7 +681,7 @@ const User = E.defineModel("User", class {
|
|
|
678
681
|
}, { pk: "id" });
|
|
679
682
|
```
|
|
680
683
|
|
|
681
|
-
#### modelBase.preCommit · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
684
|
+
#### modelBase.preCommit · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
682
685
|
|
|
683
686
|
Optional hook called on each modified instance right before the transaction commits.
|
|
684
687
|
Runs before data is written to disk, so changes made here are included in the commit.
|
|
@@ -705,19 +708,19 @@ const Post = E.defineModel("Post", class {
|
|
|
705
708
|
}, { pk: "id" });
|
|
706
709
|
```
|
|
707
710
|
|
|
708
|
-
#### modelBase.getPrimaryKey · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
711
|
+
#### modelBase.getPrimaryKey · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
709
712
|
|
|
710
713
|
**Signature:** `() => Uint8Array<ArrayBufferLike>`
|
|
711
714
|
|
|
712
715
|
**Returns:** The primary key for this instance.
|
|
713
716
|
|
|
714
|
-
#### modelBase.getPrimaryKeyHash · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
717
|
+
#### modelBase.getPrimaryKeyHash · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
715
718
|
|
|
716
719
|
**Signature:** `() => number`
|
|
717
720
|
|
|
718
721
|
**Returns:** A 53-bit positive integer non-cryptographic hash of the primary key, or undefined if not yet saved.
|
|
719
722
|
|
|
720
|
-
#### modelBase.isLazyField · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
723
|
+
#### modelBase.isLazyField · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
721
724
|
|
|
722
725
|
**Signature:** `(field: keyof this) => boolean`
|
|
723
726
|
|
|
@@ -725,7 +728,7 @@ const Post = E.defineModel("Post", class {
|
|
|
725
728
|
|
|
726
729
|
- `field: keyof this`
|
|
727
730
|
|
|
728
|
-
#### modelBase.preventPersist · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
731
|
+
#### modelBase.preventPersist · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
729
732
|
|
|
730
733
|
Prevent this instance from being persisted to the database.
|
|
731
734
|
|
|
@@ -741,7 +744,7 @@ user.name = "New Name";
|
|
|
741
744
|
user.preventPersist(); // Changes won't be saved
|
|
742
745
|
```
|
|
743
746
|
|
|
744
|
-
#### modelBase.delete · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
747
|
+
#### modelBase.delete · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
745
748
|
|
|
746
749
|
Delete this model instance from the database.
|
|
747
750
|
|
|
@@ -756,7 +759,7 @@ const user = User.get("user123");
|
|
|
756
759
|
user.delete(); // Removes from database
|
|
757
760
|
```
|
|
758
761
|
|
|
759
|
-
#### modelBase.validate · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
762
|
+
#### modelBase.validate · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
760
763
|
|
|
761
764
|
Validate all fields in this model instance.
|
|
762
765
|
|
|
@@ -778,7 +781,7 @@ if (errors.length > 0) {
|
|
|
778
781
|
}
|
|
779
782
|
```
|
|
780
783
|
|
|
781
|
-
#### modelBase.isValid · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
784
|
+
#### modelBase.isValid · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
782
785
|
|
|
783
786
|
Check if this model instance is valid.
|
|
784
787
|
|
|
@@ -793,19 +796,19 @@ const user = new User({name: "John"});
|
|
|
793
796
|
if (!user.isValid()) shoutAtTheUser();
|
|
794
797
|
```
|
|
795
798
|
|
|
796
|
-
#### modelBase.getState · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
799
|
+
#### modelBase.getState · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
797
800
|
|
|
798
801
|
**Signature:** `() => "created" | "deleted" | "loaded" | "lazy"`
|
|
799
802
|
|
|
800
|
-
#### modelBase.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
803
|
+
#### modelBase.toString · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
801
804
|
|
|
802
805
|
**Signature:** `() => string`
|
|
803
806
|
|
|
804
|
-
#### modelBase.[Symbol.for('nodejs.util.inspect.custom')] · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
807
|
+
#### modelBase.[Symbol.for('nodejs.util.inspect.custom')] · [method](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
805
808
|
|
|
806
809
|
**Signature:** `() => string`
|
|
807
810
|
|
|
808
|
-
### defineModel · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
811
|
+
### defineModel · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
809
812
|
|
|
810
813
|
Register a model class with the Edinburgh ORM system.
|
|
811
814
|
|
|
@@ -829,7 +832,7 @@ typed fields, primary key access, and optional secondary and unique indexes.
|
|
|
829
832
|
|
|
830
833
|
**Returns:** The enhanced model constructor.
|
|
831
834
|
|
|
832
|
-
### deleteEverything · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
835
|
+
### deleteEverything · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
833
836
|
|
|
834
837
|
Delete every key/value entry in the database and reinitialize all registered models.
|
|
835
838
|
|
|
@@ -868,13 +871,13 @@ const User = E.defineModel("User", class {
|
|
|
868
871
|
});
|
|
869
872
|
```
|
|
870
873
|
|
|
871
|
-
### string · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
874
|
+
### string · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
872
875
|
|
|
873
876
|
Type wrapper instance for the string type.
|
|
874
877
|
|
|
875
878
|
**Value:** `TypeWrapper<string>`
|
|
876
879
|
|
|
877
|
-
### orderedString · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
880
|
+
### orderedString · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
878
881
|
|
|
879
882
|
Type wrapper instance for the ordered string type, which is just like a string
|
|
880
883
|
except that it sorts lexicographically in the database (instead of by incrementing
|
|
@@ -884,37 +887,37 @@ may not contain null characters.
|
|
|
884
887
|
|
|
885
888
|
**Value:** `TypeWrapper<string>`
|
|
886
889
|
|
|
887
|
-
### number · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
890
|
+
### number · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
888
891
|
|
|
889
892
|
Type wrapper instance for the number type.
|
|
890
893
|
|
|
891
894
|
**Value:** `TypeWrapper<number>`
|
|
892
895
|
|
|
893
|
-
### dateTime · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
896
|
+
### dateTime · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
894
897
|
|
|
895
898
|
Type wrapper instance for the date/time type. Stored without timezone info, rounded to whole seconds.
|
|
896
899
|
|
|
897
900
|
**Value:** `TypeWrapper<Date>`
|
|
898
901
|
|
|
899
|
-
### boolean · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
902
|
+
### boolean · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
900
903
|
|
|
901
904
|
Type wrapper instance for the boolean type.
|
|
902
905
|
|
|
903
906
|
**Value:** `TypeWrapper<boolean>`
|
|
904
907
|
|
|
905
|
-
### identifier · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
908
|
+
### identifier · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
906
909
|
|
|
907
910
|
Type wrapper instance for the identifier type.
|
|
908
911
|
|
|
909
912
|
**Value:** `TypeWrapper<string>`
|
|
910
913
|
|
|
911
|
-
### undef · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
914
|
+
### undef · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
912
915
|
|
|
913
916
|
Type wrapper instance for the 'undefined' type.
|
|
914
917
|
|
|
915
918
|
**Value:** `TypeWrapper<undefined>`
|
|
916
919
|
|
|
917
|
-
### opt · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
920
|
+
### opt · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
918
921
|
|
|
919
922
|
Create an optional type wrapper (allows undefined).
|
|
920
923
|
|
|
@@ -937,7 +940,7 @@ const optionalString = E.opt(E.string);
|
|
|
937
940
|
const optionalNumber = E.opt(E.number);
|
|
938
941
|
```
|
|
939
942
|
|
|
940
|
-
### or · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
943
|
+
### or · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
941
944
|
|
|
942
945
|
Create a union type wrapper from multiple type choices.
|
|
943
946
|
|
|
@@ -960,7 +963,7 @@ const stringOrNumber = E.or(E.string, E.number);
|
|
|
960
963
|
const status = E.or("active", "inactive", "pending");
|
|
961
964
|
```
|
|
962
965
|
|
|
963
|
-
### array · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
966
|
+
### array · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
964
967
|
|
|
965
968
|
Create an array type wrapper with optional length constraints.
|
|
966
969
|
|
|
@@ -984,7 +987,7 @@ const stringArray = E.array(E.string);
|
|
|
984
987
|
const boundedArray = E.array(E.number, {min: 1, max: 10});
|
|
985
988
|
```
|
|
986
989
|
|
|
987
|
-
### set · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
990
|
+
### set · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
988
991
|
|
|
989
992
|
Create a Set type wrapper with optional length constraints.
|
|
990
993
|
|
|
@@ -1008,7 +1011,7 @@ const stringSet = E.set(E.string);
|
|
|
1008
1011
|
const boundedSet = E.set(E.number, {min: 1, max: 10});
|
|
1009
1012
|
```
|
|
1010
1013
|
|
|
1011
|
-
### record · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1014
|
+
### record · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
1012
1015
|
|
|
1013
1016
|
Create a Record type wrapper for key-value objects with string or number keys.
|
|
1014
1017
|
|
|
@@ -1030,7 +1033,7 @@ Create a Record type wrapper for key-value objects with string or number keys.
|
|
|
1030
1033
|
const scores = E.record(E.number); // Record<string | number, number>
|
|
1031
1034
|
```
|
|
1032
1035
|
|
|
1033
|
-
### literal · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1036
|
+
### literal · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
1034
1037
|
|
|
1035
1038
|
Create a literal type wrapper for a constant value.
|
|
1036
1039
|
|
|
@@ -1053,7 +1056,7 @@ const statusType = E.literal("active");
|
|
|
1053
1056
|
const countType = E.literal(42);
|
|
1054
1057
|
```
|
|
1055
1058
|
|
|
1056
|
-
### link · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1059
|
+
### link · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
1057
1060
|
|
|
1058
1061
|
Create a link type wrapper for model relationships.
|
|
1059
1062
|
|
|
@@ -1083,7 +1086,7 @@ const Book = E.defineModel("Book", class {
|
|
|
1083
1086
|
}, { pk: "id" });
|
|
1084
1087
|
```
|
|
1085
1088
|
|
|
1086
|
-
### dump · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1089
|
+
### dump · [function](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L252)
|
|
1087
1090
|
|
|
1088
1091
|
**Signature:** `() => void`
|
|
1089
1092
|
|
|
@@ -1273,7 +1276,7 @@ Check if indexing should be skipped for this field value.
|
|
|
1273
1276
|
|
|
1274
1277
|
**Signature:** `() => AnyModelClass`
|
|
1275
1278
|
|
|
1276
|
-
### DatabaseError · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#
|
|
1279
|
+
### DatabaseError · [constant](https://github.com/vanviegen/edinburgh/blob/main/src/edinburgh.ts#L174)
|
|
1277
1280
|
|
|
1278
1281
|
The DatabaseError class is used to represent errors that occur during database operations.
|
|
1279
1282
|
It extends the built-in Error class and has a machine readable error code string property.
|
package/build/src/edinburgh.d.ts
CHANGED
|
@@ -84,5 +84,8 @@ export declare function setMaxRetryCount(count: number): void;
|
|
|
84
84
|
* `transact()` commit that has changes, with the following arguments:
|
|
85
85
|
* - A sequential number. Higher numbers have been committed after lower numbers.
|
|
86
86
|
* - A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
87
|
+
*
|
|
88
|
+
* The callback is called within a new transaction context, allowing lazy-loads to happen. However, any
|
|
89
|
+
* changes made to Edinburgh models will not be saved.
|
|
87
90
|
*/
|
|
88
91
|
export declare function setOnSaveCallback(callback: ((commitId: number, items: Map<Model<unknown>, Change>) => void) | undefined): void;
|
package/build/src/edinburgh.js
CHANGED
|
@@ -140,27 +140,31 @@ export async function transact(fn) {
|
|
|
140
140
|
catch { }
|
|
141
141
|
throw e;
|
|
142
142
|
}
|
|
143
|
-
|
|
144
|
-
//
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// this point, and to help the GC reclaim memory.
|
|
152
|
-
txn.id = txn.instances = undefined;
|
|
153
|
-
}
|
|
154
|
-
const commitResult = lowlevel.commitTransaction(txnId);
|
|
155
|
-
const commitSeq = typeof commitResult === 'number' ? commitResult : await commitResult;
|
|
156
|
-
if (commitSeq > 0) {
|
|
157
|
-
// Success
|
|
158
|
-
if (onSaveItems?.size) {
|
|
143
|
+
if (onSaveItems?.size) {
|
|
144
|
+
// Perform writes, and start a new transaction at or past the point-in-time of our commit
|
|
145
|
+
const commitResult = lowlevel.commitTransaction(txnId, true);
|
|
146
|
+
if (typeof commitResult === 'object') {
|
|
147
|
+
const commitSeq = await commitResult;
|
|
148
|
+
if (commitSeq <= 0)
|
|
149
|
+
continue; // Race condition - retry
|
|
150
|
+
// Run the callback within our new transaction context, so it can fetch linked lazy fields if needed
|
|
159
151
|
onSaveCallback(commitSeq, onSaveItems);
|
|
160
152
|
}
|
|
161
|
-
|
|
153
|
+
// else: only reads
|
|
162
154
|
}
|
|
163
|
-
//
|
|
155
|
+
// Make the instances read-only to make it clear that their transaction has ended.
|
|
156
|
+
for (const instance of txn.instances.values()) {
|
|
157
|
+
delete instance._oldValues;
|
|
158
|
+
Object.defineProperty(instance, "_txn", STALE_INSTANCE_DESCRIPTOR);
|
|
159
|
+
Object.freeze(instance);
|
|
160
|
+
}
|
|
161
|
+
// Destroy the transaction object, to make sure things crash if they are used after
|
|
162
|
+
// this point, and to help the GC reclaim memory.
|
|
163
|
+
txn.id = txn.instances = undefined;
|
|
164
|
+
// Commit the transaction and actually end it
|
|
165
|
+
if ((await lowlevel.commitTransaction(txnId)) <= 0)
|
|
166
|
+
continue; // Race condition - retry
|
|
167
|
+
return result;
|
|
164
168
|
}
|
|
165
169
|
throw new DatabaseError("Transaction keeps getting raced", "RACING_TRANSACTION");
|
|
166
170
|
// } catch (e: Error | any) {
|
|
@@ -187,6 +191,9 @@ let onSaveCallback;
|
|
|
187
191
|
* `transact()` commit that has changes, with the following arguments:
|
|
188
192
|
* - A sequential number. Higher numbers have been committed after lower numbers.
|
|
189
193
|
* - A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
194
|
+
*
|
|
195
|
+
* The callback is called within a new transaction context, allowing lazy-loads to happen. However, any
|
|
196
|
+
* changes made to Edinburgh models will not be saved.
|
|
190
197
|
*/
|
|
191
198
|
export function setOnSaveCallback(callback) {
|
|
192
199
|
onSaveCallback = callback;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edinburgh.js","sourceRoot":"","sources":["../../src/edinburgh.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"edinburgh.js","sourceRoot":"","sources":["../../src/edinburgh.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "edinburgh",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"author": "Frank van Viegen",
|
|
5
5
|
"devDependencies": {
|
|
6
6
|
"@types/bun": "^1.2.16",
|
|
@@ -56,6 +56,6 @@
|
|
|
56
56
|
],
|
|
57
57
|
"type": "module",
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"olmdb": "^0.4.
|
|
59
|
+
"olmdb": "^0.4.2"
|
|
60
60
|
}
|
|
61
61
|
}
|
|
@@ -10,3 +10,6 @@ Set a callback function to be called after a model is saved and committed.
|
|
|
10
10
|
`transact()` commit that has changes, with the following arguments:
|
|
11
11
|
- A sequential number. Higher numbers have been committed after lower numbers.
|
|
12
12
|
- A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
13
|
+
|
|
14
|
+
The callback is called within a new transaction context, allowing lazy-loads to happen. However, any
|
|
15
|
+
changes made to Edinburgh models will not be saved.
|
package/src/edinburgh.ts
CHANGED
|
@@ -183,30 +183,36 @@ export async function transact<T>(fn: () => T): Promise<T> {
|
|
|
183
183
|
} catch (e: any) {
|
|
184
184
|
try { lowlevel.abortTransaction(txnId); } catch {}
|
|
185
185
|
throw e;
|
|
186
|
-
} finally {
|
|
187
|
-
// Make the instances read-only to make it clear that their transaction has ended.
|
|
188
|
-
for (const instance of txn.instances.values()) {
|
|
189
|
-
delete instance._oldValues;
|
|
190
|
-
Object.defineProperty(instance, "_txn", STALE_INSTANCE_DESCRIPTOR);
|
|
191
|
-
Object.freeze(instance);
|
|
192
|
-
}
|
|
193
|
-
// Destroy the transaction object, to make sure things crash if they are used after
|
|
194
|
-
// this point, and to help the GC reclaim memory.
|
|
195
|
-
txn.id = txn.instances = undefined as any;
|
|
196
186
|
}
|
|
197
187
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
188
|
+
if (onSaveItems?.size) {
|
|
189
|
+
// Perform writes, and start a new transaction at or past the point-in-time of our commit
|
|
190
|
+
const commitResult = lowlevel.commitTransaction(txnId, true);
|
|
191
|
+
if (typeof commitResult === 'object') {
|
|
192
|
+
const commitSeq = await commitResult;
|
|
193
|
+
if (commitSeq <= 0) continue; // Race condition - retry
|
|
194
|
+
// Run the callback within our new transaction context, so it can fetch linked lazy fields if needed
|
|
204
195
|
onSaveCallback!(commitSeq, onSaveItems);
|
|
205
196
|
}
|
|
206
|
-
|
|
197
|
+
// else: only reads
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Make the instances read-only to make it clear that their transaction has ended.
|
|
201
|
+
for (const instance of txn.instances.values()) {
|
|
202
|
+
delete instance._oldValues;
|
|
203
|
+
Object.defineProperty(instance, "_txn", STALE_INSTANCE_DESCRIPTOR);
|
|
204
|
+
Object.freeze(instance);
|
|
207
205
|
}
|
|
208
206
|
|
|
209
|
-
//
|
|
207
|
+
// Destroy the transaction object, to make sure things crash if they are used after
|
|
208
|
+
// this point, and to help the GC reclaim memory.
|
|
209
|
+
txn.id = txn.instances = undefined as any;
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
// Commit the transaction and actually end it
|
|
213
|
+
if ((await lowlevel.commitTransaction(txnId)) <= 0) continue; // Race condition - retry
|
|
214
|
+
|
|
215
|
+
return result as T;
|
|
210
216
|
}
|
|
211
217
|
throw new DatabaseError("Transaction keeps getting raced", "RACING_TRANSACTION");
|
|
212
218
|
// } catch (e: Error | any) {
|
|
@@ -236,6 +242,9 @@ let onSaveCallback: ((commitId: number, items: Map<Model<unknown>, Change>) => v
|
|
|
236
242
|
* `transact()` commit that has changes, with the following arguments:
|
|
237
243
|
* - A sequential number. Higher numbers have been committed after lower numbers.
|
|
238
244
|
* - A map of model instances to their changes. The change can be "created", "deleted", or an object containing the old values.
|
|
245
|
+
*
|
|
246
|
+
* The callback is called within a new transaction context, allowing lazy-loads to happen. However, any
|
|
247
|
+
* changes made to Edinburgh models will not be saved.
|
|
239
248
|
*/
|
|
240
249
|
export function setOnSaveCallback(callback: ((commitId: number, items: Map<Model<unknown>, Change>) => void) | undefined) {
|
|
241
250
|
onSaveCallback = callback;
|