@@ -45,12 +45,64 @@ export class WalletClient {
4545 private walletName : string ;
4646 private networkId : string ;
4747 private dataStore : DataStore | null = null ;
48+ private inFlightDocumentOps = 0 ;
49+ private idleWaiters : Array < ( ) => void > = [ ] ;
4850
4951 constructor ( walletName : string = "default-wallet" , networkId : string = "testnet" ) {
5052 this . walletName = walletName ;
5153 this . networkId = networkId ;
5254 }
5355
56+ private trackDocumentOperation < T > ( operation : Promise < T > ) : Promise < T > {
57+ this . inFlightDocumentOps += 1 ;
58+
59+ return operation . finally ( ( ) => {
60+ this . inFlightDocumentOps = Math . max ( 0 , this . inFlightDocumentOps - 1 ) ;
61+
62+ if ( this . inFlightDocumentOps === 0 ) {
63+ const waiters = this . idleWaiters . splice ( 0 ) ;
64+ for ( const resolve of waiters ) {
65+ resolve ( ) ;
66+ }
67+ }
68+ } ) ;
69+ }
70+
71+ /**
72+ * Wait until tracked document operations settle.
73+ * This avoids brittle fixed sleeps in integration tests.
74+ */
75+ async waitForIdle ( timeoutMs : number = 10000 ) : Promise < void > {
76+ const start = Date . now ( ) ;
77+
78+ while ( true ) {
79+ if ( this . inFlightDocumentOps === 0 ) {
80+ // Ensure no new operations were queued in the same tick.
81+ await new Promise < void > ( ( resolve ) => setImmediate ( resolve ) ) ;
82+ if ( this . inFlightDocumentOps === 0 ) {
83+ return ;
84+ }
85+ }
86+
87+ const elapsed = Date . now ( ) - start ;
88+ const remaining = timeoutMs - elapsed ;
89+ if ( remaining <= 0 ) {
90+ throw new Error ( `Timed out waiting for wallet document operations to settle after ${ timeoutMs } ms` ) ;
91+ }
92+
93+ await new Promise < void > ( ( resolve , reject ) => {
94+ const timeoutId = setTimeout ( ( ) => {
95+ reject ( new Error ( `Timed out waiting for wallet document operations to settle after ${ timeoutMs } ms` ) ) ;
96+ } , remaining ) ;
97+
98+ this . idleWaiters . push ( ( ) => {
99+ clearTimeout ( timeoutId ) ;
100+ resolve ( ) ;
101+ } ) ;
102+ } ) ;
103+ }
104+ }
105+
54106 /**
55107 * Initialize the wallet
56108 */
@@ -75,14 +127,14 @@ export class WalletClient {
75127 } ,
76128 dataSource,
77129 documentStore : {
78- addDocument : ( json , options ) => createDocument ( { dataStore, json, options } ) ,
79- removeDocument : ( id , options ) => removeDocument ( { dataStore, id, options } ) ,
80- updateDocument : ( document , options ) => updateDocument ( { dataStore, document, options } ) ,
130+ addDocument : ( json , options ) => this . trackDocumentOperation ( createDocument ( { dataStore, json, options } ) ) ,
131+ removeDocument : ( id , options ) => this . trackDocumentOperation ( removeDocument ( { dataStore, id, options } ) ) ,
132+ updateDocument : ( document , options ) => this . trackDocumentOperation ( updateDocument ( { dataStore, document, options } ) ) ,
81133 getDocumentById : ( id ) => getDocumentById ( { dataStore, id } ) ,
82134 getDocumentsByType : ( type ) => getDocumentsByType ( { dataStore, type } ) ,
83135 getDocumentsById : ( idList ) => getDocumentsById ( { dataStore, idList } ) ,
84136 getAllDocuments : ( allNetworks ) => getAllDocuments ( { dataStore, allNetworks } ) ,
85- removeAllDocuments : ( ) => removeAllDocuments ( { dataStore } ) ,
137+ removeAllDocuments : ( ) => this . trackDocumentOperation ( removeAllDocuments ( { dataStore } ) ) ,
86138 getDocumentCorrelations : ( documentId ) => getDocumentCorrelations ( { dataStore, documentId } ) ,
87139 } ,
88140 localStorageImpl,
@@ -161,14 +213,13 @@ export class WalletClient {
161213
162214 // Call wallet cleanup
163215 try {
216+ await this . waitForIdle ( ) ;
164217 await this . wallet . deleteWallet ( ) ;
218+ await this . waitForIdle ( ) ;
165219 } catch ( err ) {
166220 console . debug ( "Error in wallet.deleteWallet():" , err ) ;
167221 }
168222
169- // Wait for async operations to settle before cleanup
170- await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
171-
172223 // Null out references to allow garbage collection
173224 this . wallet = null ;
174225 this . dataStore = null ;
0 commit comments