@@ -9,12 +9,14 @@ import type {
9
9
NetworkData ,
10
10
Vault ,
11
11
} from '@fuel-wallet/types' ;
12
- import type { Table } from 'dexie' ;
12
+ import type { DbEvents , PromiseExtended , Table } from 'dexie' ;
13
13
import Dexie from 'dexie' ;
14
14
import 'dexie-observable' ;
15
15
import { DATABASE_VERSION , VITE_FUEL_PROVIDER_URL } from '~/config' ;
16
16
import type { Transaction } from '~/systems/Transaction/types' ;
17
17
18
+ type FailureEvents = Extract < keyof DbEvents , 'close' | 'blocked' > ;
19
+
18
20
export class FuelDB extends Dexie {
19
21
vaults ! : Table < Vault , string > ;
20
22
accounts ! : Table < Account , string > ;
@@ -24,6 +26,8 @@ export class FuelDB extends Dexie {
24
26
assets ! : Table < AssetData , string > ;
25
27
abis ! : Table < AbiTable , string > ;
26
28
errors ! : Table < FuelWalletError , string > ;
29
+ integrityCheckInterval ?: NodeJS . Timeout ;
30
+ restartAttempts = 0 ;
27
31
readonly alwaysOpen = true ;
28
32
29
33
constructor ( ) {
@@ -51,16 +55,70 @@ export class FuelDB extends Dexie {
51
55
id : createUUID ( ) ,
52
56
} ) ;
53
57
} ) ;
54
- this . on ( 'blocked' , ( ) => this . restart ( 'closed' ) ) ;
55
- this . on ( 'close' , ( ) => this . restart ( 'blocked' ) ) ;
58
+ this . on ( 'blocked' , ( ) => this . restart ( 'blocked' ) ) ;
59
+ this . on ( 'close' , ( ) => this . restart ( 'close' ) ) ;
60
+ this . on ( 'message' , ( e ) => {
61
+ console . log ( 'fsk changed' , e ) ;
62
+ } ) ;
63
+ }
64
+
65
+ open ( ) {
66
+ return this . safeOpen ( ) . finally ( ( ) =>
67
+ this . watchConnection ( )
68
+ ) as PromiseExtended < Dexie > ;
69
+ }
70
+
71
+ close ( safeClose = false ) {
72
+ if ( safeClose ) {
73
+ this . restartAttempts = 0 ;
74
+ clearInterval ( this . integrityCheckInterval ) ;
75
+ }
76
+ return super . close ( ) ;
77
+ }
78
+
79
+ async safeOpen ( ) {
80
+ try {
81
+ const result = await super . open ( ) ;
82
+ this . restartAttempts = 0 ;
83
+ return result ;
84
+ } catch ( err ) {
85
+ console . error ( 'Failed to restart DB. Sending signal for restart' ) ;
86
+ this . restart ( 'blocked' ) ;
87
+ throw err ;
88
+ }
89
+ }
90
+
91
+ async ensureDatabaseOpen ( ) {
92
+ if ( this . isOpen ( ) && ! this . hasBeenClosed ( ) && ! this . hasFailed ( ) ) return ;
93
+
94
+ if ( this . restartAttempts > 3 ) {
95
+ console . error ( 'Reached max attempts to open DB. Sending restart signal.' ) ;
96
+ this . restart ( 'blocked' ) ;
97
+ return ;
98
+ }
99
+
100
+ this . restartAttempts += 1 ;
101
+ console . warn ( 'DB is not open. Attempting restart.' ) ;
102
+ await this . safeOpen ( ) ;
103
+ }
104
+
105
+ watchConnection ( ) {
106
+ if ( ! this . alwaysOpen ) return ;
107
+
108
+ clearInterval ( this . integrityCheckInterval ) ;
109
+ this . integrityCheckInterval = setInterval ( ( ) => {
110
+ this . ensureDatabaseOpen ( ) ;
111
+ } , 1000 ) ;
56
112
}
57
113
58
- async restart ( eventName : 'blocked' | 'closed' ) {
114
+ async restart ( eventName : FailureEvents ) {
59
115
if ( ! this . alwaysOpen ) {
60
116
return ;
61
117
}
62
- if ( eventName !== 'closed' ) {
63
- this . close ( ) ;
118
+ if ( eventName === 'close' ) {
119
+ clearInterval ( this . integrityCheckInterval ) ;
120
+ } else {
121
+ this . close ( true ) ;
64
122
}
65
123
66
124
this . open ( ) ;
0 commit comments