@forcecalendar/core 2.1.1 → 2.1.3
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/core/events/EventStore.js +47 -8
- package/package.json +1 -1
|
@@ -46,6 +46,8 @@ export class EventStore {
|
|
|
46
46
|
this.isBatchMode = false;
|
|
47
47
|
this.batchNotifications = [];
|
|
48
48
|
this.batchBackup = null; // For rollback support
|
|
49
|
+
this._batchLock = null; // Lock to prevent concurrent batch operations
|
|
50
|
+
this._batchLockResolve = null; // Resolver for the batch lock
|
|
49
51
|
|
|
50
52
|
// Change tracking
|
|
51
53
|
/** @type {number} */
|
|
@@ -804,6 +806,22 @@ export class EventStore {
|
|
|
804
806
|
}
|
|
805
807
|
}
|
|
806
808
|
|
|
809
|
+
// Remove from category indices
|
|
810
|
+
for (const [category, eventIds] of this.indices.byCategory) {
|
|
811
|
+
eventIds.delete(event.id);
|
|
812
|
+
if (eventIds.size === 0) {
|
|
813
|
+
this.indices.byCategory.delete(category);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
// Remove from status indices
|
|
818
|
+
for (const [status, eventIds] of this.indices.byStatus) {
|
|
819
|
+
eventIds.delete(event.id);
|
|
820
|
+
if (eventIds.size === 0) {
|
|
821
|
+
this.indices.byStatus.delete(status);
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
807
825
|
// Remove from recurring index
|
|
808
826
|
this.indices.recurring.delete(event.id);
|
|
809
827
|
}
|
|
@@ -924,23 +942,44 @@ export class EventStore {
|
|
|
924
942
|
|
|
925
943
|
/**
|
|
926
944
|
* Execute batch operation with automatic rollback on error
|
|
945
|
+
* Uses a lock to prevent concurrent batch operations from corrupting state
|
|
927
946
|
* @param {Function} operation - Operation to execute
|
|
928
947
|
* @param {boolean} [enableRollback=true] - Enable automatic rollback on error
|
|
929
948
|
* @returns {*} Result of operation
|
|
930
949
|
* @throws {Error} If operation fails
|
|
931
950
|
*/
|
|
932
951
|
async executeBatch(operation, enableRollback = true) {
|
|
933
|
-
|
|
952
|
+
// Wait for any existing batch operation to complete
|
|
953
|
+
while (this._batchLock) {
|
|
954
|
+
await this._batchLock;
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
// Acquire the lock
|
|
958
|
+
this._batchLock = new Promise(resolve => {
|
|
959
|
+
this._batchLockResolve = resolve;
|
|
960
|
+
});
|
|
934
961
|
|
|
935
962
|
try {
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
963
|
+
this.startBatch(enableRollback);
|
|
964
|
+
|
|
965
|
+
try {
|
|
966
|
+
const result = await operation();
|
|
967
|
+
this.commitBatch();
|
|
968
|
+
return result;
|
|
969
|
+
} catch (error) {
|
|
970
|
+
if (enableRollback) {
|
|
971
|
+
this.rollbackBatch();
|
|
972
|
+
}
|
|
973
|
+
throw error;
|
|
974
|
+
}
|
|
975
|
+
} finally {
|
|
976
|
+
// Release the lock
|
|
977
|
+
const resolve = this._batchLockResolve;
|
|
978
|
+
this._batchLock = null;
|
|
979
|
+
this._batchLockResolve = null;
|
|
980
|
+
if (resolve) {
|
|
981
|
+
resolve();
|
|
942
982
|
}
|
|
943
|
-
throw error;
|
|
944
983
|
}
|
|
945
984
|
}
|
|
946
985
|
|