@bopen-io/wallet-toolbox 1.7.20-idb-fix.2 → 1.7.20-idb-fix.5
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/out/src/storage/StorageIdb.d.ts.map +1 -1
- package/out/src/storage/StorageIdb.js +24 -6
- package/out/src/storage/StorageIdb.js.map +1 -1
- package/out/src/storage/WalletStorageManager.d.ts.map +1 -1
- package/out/src/storage/WalletStorageManager.js +81 -31
- package/out/src/storage/WalletStorageManager.js.map +1 -1
- package/out/tsconfig.all.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/storage/WalletStorageManager.ts +84 -40
package/package.json
CHANGED
|
@@ -744,23 +744,27 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
744
744
|
const identityKey = auth.identityKey
|
|
745
745
|
|
|
746
746
|
const writerSettings = await writer.makeAvailable()
|
|
747
|
+
const isRemoteWriter = writer instanceof StorageClient
|
|
747
748
|
|
|
748
749
|
let inserts = 0,
|
|
749
750
|
updates = 0
|
|
750
751
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
752
|
+
// If writer is remote (StorageClient), we must NOT hold a local IDB transaction
|
|
753
|
+
// across network calls. Instead, do fresh reads for each chunk iteration.
|
|
754
|
+
if (isRemoteWriter && !activeSync) {
|
|
755
|
+
const readerSettings = this.getSettings()
|
|
755
756
|
log += progLog(`syncToWriter from ${readerSettings.storageName} to ${writerSettings.storageName}\n`)
|
|
756
757
|
|
|
757
758
|
let i = -1
|
|
758
759
|
for (;;) {
|
|
759
760
|
i++
|
|
761
|
+
// Network call to remote writer - OK, no local transaction held
|
|
760
762
|
const ss = await EntitySyncState.fromStorage(writer, identityKey, readerSettings)
|
|
761
763
|
const args = ss.makeRequestSyncChunkArgs(identityKey, writerSettings.storageIdentityKey)
|
|
762
|
-
|
|
764
|
+
// Fresh local read - brief transaction that completes before network call
|
|
765
|
+
const chunk = await this.runAsSync(async sync => sync.getSyncChunk(args))
|
|
763
766
|
log += EntitySyncState.syncChunkSummary(chunk)
|
|
767
|
+
// Network call to remote writer - OK, no local transaction held
|
|
764
768
|
const r = await writer.processSyncChunk(args, chunk)
|
|
765
769
|
inserts += r.inserts
|
|
766
770
|
updates += r.updates
|
|
@@ -768,8 +772,31 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
768
772
|
if (r.done) break
|
|
769
773
|
}
|
|
770
774
|
log += progLog(`syncToWriter complete: ${inserts} inserts, ${updates} updates\n`)
|
|
771
|
-
|
|
772
|
-
|
|
775
|
+
} else {
|
|
776
|
+
// Writer is local or we have an active sync context - use original approach
|
|
777
|
+
log = await this.runAsSync(async sync => {
|
|
778
|
+
const reader = sync
|
|
779
|
+
const readerSettings = reader.getSettings()
|
|
780
|
+
|
|
781
|
+
log += progLog(`syncToWriter from ${readerSettings.storageName} to ${writerSettings.storageName}\n`)
|
|
782
|
+
|
|
783
|
+
let i = -1
|
|
784
|
+
for (;;) {
|
|
785
|
+
i++
|
|
786
|
+
const ss = await EntitySyncState.fromStorage(writer, identityKey, readerSettings)
|
|
787
|
+
const args = ss.makeRequestSyncChunkArgs(identityKey, writerSettings.storageIdentityKey)
|
|
788
|
+
const chunk = await reader.getSyncChunk(args)
|
|
789
|
+
log += EntitySyncState.syncChunkSummary(chunk)
|
|
790
|
+
const r = await writer.processSyncChunk(args, chunk)
|
|
791
|
+
inserts += r.inserts
|
|
792
|
+
updates += r.updates
|
|
793
|
+
log += progLog(`chunk ${i} inserted ${r.inserts} updated ${r.updates} ${r.maxUpdated_at}\n`)
|
|
794
|
+
if (r.done) break
|
|
795
|
+
}
|
|
796
|
+
log += progLog(`syncToWriter complete: ${inserts} inserts, ${updates} updates\n`)
|
|
797
|
+
return log
|
|
798
|
+
}, activeSync)
|
|
799
|
+
}
|
|
773
800
|
|
|
774
801
|
return { inserts, updates, log }
|
|
775
802
|
}
|
|
@@ -817,38 +844,55 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
817
844
|
|
|
818
845
|
log += progLog('\n')
|
|
819
846
|
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
+
// Handle conflicting actives OUTSIDE runAsSync to avoid IDB timeout.
|
|
848
|
+
// Network calls to remote storage can take longer than IDB transaction timeout.
|
|
849
|
+
if (this._conflictingActives!.length > 0) {
|
|
850
|
+
// Handle case where new active is current active to resolve conflicts.
|
|
851
|
+
// And where new active is one of the current conflict actives.
|
|
852
|
+
this._conflictingActives!.push(this._active!)
|
|
853
|
+
// Remove the new active from conflicting actives
|
|
854
|
+
this._conflictingActives = this._conflictingActives!.filter(ca => {
|
|
855
|
+
const isNewActive = ca.settings!.storageIdentityKey === storageIdentityKey
|
|
856
|
+
return !isNewActive
|
|
857
|
+
})
|
|
858
|
+
|
|
859
|
+
// Merge state from each conflicting active into newActive.
|
|
860
|
+
// Network calls happen here, outside any held IDB transaction.
|
|
861
|
+
for (const conflict of this._conflictingActives) {
|
|
862
|
+
log += progLog('MERGING STATE FROM CONFLICTING ACTIVES:\n')
|
|
863
|
+
const readerSettings = await conflict.storage.makeAvailable()
|
|
864
|
+
const writerSettings = await newActive.storage.makeAvailable()
|
|
865
|
+
|
|
866
|
+
let i = -1
|
|
867
|
+
for (;;) {
|
|
868
|
+
i++
|
|
869
|
+
// Get sync state from writer (newActive) - brief local read
|
|
870
|
+
const ss = await EntitySyncState.fromStorage(newActive.storage, identityKey, readerSettings)
|
|
871
|
+
const args = ss.makeRequestSyncChunkArgs(identityKey, writerSettings.storageIdentityKey)
|
|
872
|
+
|
|
873
|
+
// Network call to conflict (reader) - outside transaction
|
|
874
|
+
const chunk = await conflict.storage.getSyncChunk(args)
|
|
875
|
+
log += EntitySyncState.syncChunkSummary(chunk)
|
|
876
|
+
|
|
877
|
+
// Preserve activeStorage - merging from reader cannot change active
|
|
878
|
+
if (chunk.user) {
|
|
879
|
+
chunk.user.activeStorage = storageIdentityKey
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
// Brief local write per chunk
|
|
883
|
+
const r = await newActive.storage.processSyncChunk(args, chunk)
|
|
884
|
+
log += progLog(`chunk ${i} inserted ${r.inserts} updated ${r.updates} ${r.maxUpdated_at}\n`)
|
|
885
|
+
if (r.done) break
|
|
847
886
|
}
|
|
848
|
-
log += progLog('PROPAGATE MERGED ACTIVE STATE TO NON-ACTIVES\n')
|
|
849
|
-
} else {
|
|
850
|
-
log += progLog('BACKUP CURRENT ACTIVE STATE THEN SET NEW ACTIVE\n')
|
|
851
887
|
}
|
|
888
|
+
log += progLog('PROPAGATE MERGED ACTIVE STATE TO NON-ACTIVES\n')
|
|
889
|
+
} else {
|
|
890
|
+
log += progLog('BACKUP CURRENT ACTIVE STATE THEN SET NEW ACTIVE\n')
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
// Continue with local-only operations in runAsSync
|
|
894
|
+
log += await this.runAsSync(async sync => {
|
|
895
|
+
let innerLog = ''
|
|
852
896
|
|
|
853
897
|
// If there were conflicting actives,
|
|
854
898
|
// Push state merged from all merged actives into newActive to all stores other than the now single active.
|
|
@@ -869,18 +913,18 @@ export class WalletStorageManager implements sdk.WalletStorage {
|
|
|
869
913
|
const stwr = await this.syncToWriter(
|
|
870
914
|
{ identityKey, userId: store.user!.userId, isActive: false },
|
|
871
915
|
store.storage,
|
|
872
|
-
|
|
916
|
+
sync,
|
|
873
917
|
undefined,
|
|
874
918
|
progLog
|
|
875
919
|
)
|
|
876
|
-
|
|
920
|
+
innerLog += stwr.log
|
|
877
921
|
}
|
|
878
922
|
}
|
|
879
923
|
|
|
880
924
|
this._isAvailable = false
|
|
881
925
|
await this.makeAvailable()
|
|
882
926
|
|
|
883
|
-
return
|
|
927
|
+
return innerLog
|
|
884
928
|
})
|
|
885
929
|
|
|
886
930
|
return log
|