@@ -121,12 +121,45 @@ export class ManageTreeNodes {
121121 let treeData = [ ] ;
122122 if ( url ) {
123123 try {
124- const res = await api . get ( url ) ;
124+ const res = await api . get ( url , { timeout : 30000 } ) ;
125125 treeData = res . data . data ;
126126 } catch ( error ) {
127127 /* react-aspen does not handle reject case */
128128 console . error ( error ) ;
129- pgAdmin . Browser . notifier . error ( parseApiError ( error ) || 'Node Load Error...' ) ;
129+ if ( error . response ?. status === 503 &&
130+ error . response ?. data ?. info === 'CONNECTION_LOST' ) {
131+ // Connection dropped while idle. Walk up to the server node
132+ // and mark it disconnected, then show a reconnect prompt so
133+ // the user can re-establish instead of seeing a silent
134+ // spinner.
135+ let serverNode = node ;
136+ while ( serverNode ) {
137+ const d = serverNode . metadata ?. data ?? serverNode . data ;
138+ if ( d ?. _type === 'server' ) break ;
139+ serverNode = serverNode . parentNode ?? null ;
140+ }
141+ if ( serverNode ) {
142+ const sData = serverNode . metadata ?. data ?? serverNode . data ;
143+ if ( sData ) sData . connected = false ;
144+ pgAdmin . Browser . tree ?. addIcon ( serverNode , { icon : 'icon-server-not-connected' } ) ;
145+ pgAdmin . Browser . tree ?. close ( serverNode ) ;
146+ }
147+ pgAdmin . Browser . notifier . confirm (
148+ gettext ( 'Connection lost' ) ,
149+ gettext ( 'The connection to the server has been lost. Would you like to reconnect?' ) ,
150+ function ( ) {
151+ // Re-open (connect) the server node in the tree which
152+ // will trigger the standard connect-to-server flow
153+ // including any password prompts.
154+ if ( serverNode && pgAdmin . Browser . tree ) {
155+ pgAdmin . Browser . tree . toggle ( serverNode ) ;
156+ }
157+ } ,
158+ function ( ) { /* cancelled */ }
159+ ) ;
160+ } else {
161+ pgAdmin . Browser . notifier . error ( parseApiError ( error ) || 'Node Load Error...' ) ;
162+ }
130163 return [ ] ;
131164 }
132165 }
0 commit comments