@@ -12,6 +12,7 @@ import ReplayTime from '~backend/api/ReplayTime';
1212export default class ReplayApi {
1313 public static serverProcess : ChildProcess ;
1414 public static serverStartPath : string ;
15+ public static nodePath : string ;
1516 private static sessions = new Set < http2 . ClientHttp2Session > ( ) ;
1617 private static localApiHost : string ;
1718
@@ -21,6 +22,7 @@ export default class ReplayApi {
2122 public lastActivityDate : Date ;
2223 public lastCommandName : string ;
2324 public showUnresponsiveMessage = true ;
25+ public hasAllData = false ;
2426
2527 public onNewTab ?: ( tab : ReplayTabState ) => any ;
2628
@@ -52,25 +54,34 @@ export default class ReplayApi {
5254 ReplayApi . sessions . add ( this . http2Session ) ;
5355 this . http2Session . on ( 'close' , ( ) => {
5456 ReplayApi . sessions . delete ( this . http2Session ) ;
57+ this . http2Session . unref ( ) ;
5558 console . log ( 'Http2 Session closed' ) ;
5659 } ) ;
5760 this . http2Session . on ( 'stream' , this . onStream . bind ( this ) ) ;
5861
5962 const request = this . http2Session
60- . request ( {
61- ':path' : `/` ,
62- 'data-location' : this . saSession . dataLocation ,
63- 'session-name' : this . saSession . name ,
64- 'session-id' : this . saSession . id ,
65- 'script-instance-id' : this . saSession . scriptInstanceId ,
66- 'script-entrypoint' : this . saSession . scriptEntrypoint ,
67- } )
63+ . request (
64+ {
65+ ':path' : `/` ,
66+ 'data-location' : this . saSession . dataLocation ,
67+ 'session-name' : this . saSession . name ,
68+ 'session-id' : this . saSession . id ,
69+ 'script-instance-id' : this . saSession . scriptInstanceId ,
70+ 'script-entrypoint' : this . saSession . scriptEntrypoint ,
71+ } ,
72+ { waitForTrailers : true } ,
73+ )
6874 . on ( 'response' , async headers => {
6975 const status = headers [ ':status' ] ;
7076 if ( status !== 200 ) {
7177 const data = await streamToJson < { message : string } > ( request ) ;
7278 this . isReadyResolvable . reject ( new Error ( data . message ?? 'Unexpected Error' ) ) ;
7379 }
80+ } )
81+ . on ( 'trailers' , trailers => {
82+ console . log ( 'Got Replay API Trailer' , trailers ) ;
83+ this . hasAllData = true ;
84+ for ( const tab of this . tabs ) tab . hasAllData = true ;
7485 } ) ;
7586 }
7687
@@ -194,8 +205,8 @@ export default class ReplayApi {
194205 ! ! ReplayApi . serverProcess ,
195206 ReplayApi . sessions . size ,
196207 ) ;
197- if ( ReplayApi . serverProcess ) ReplayApi . serverProcess . kill ( ) ;
198208 for ( const session of ReplayApi . sessions ) session . destroy ( ) ;
209+ if ( ReplayApi . serverProcess ) ReplayApi . serverProcess . kill ( ) ;
199210 }
200211
201212 public static async connect ( replay : IReplayMeta ) {
@@ -217,8 +228,9 @@ export default class ReplayApi {
217228 const replayDir = __dirname . split ( `${ Path . sep } replay${ Path . sep } ` ) . shift ( ) ;
218229 this . serverStartPath = Path . resolve ( replayDir , 'session-state/api/start' ) ;
219230 }
231+ if ( ! this . nodePath ) this . nodePath = 'node' ;
220232 console . log ( 'Launching Replay API Server at %s' , this . serverStartPath ) ;
221- const child = spawn ( `node "${ this . serverStartPath } "` , args , {
233+ const child = spawn ( `${ this . nodePath } "${ this . serverStartPath } "` , args , {
222234 stdio : [ 'ignore' , 'pipe' , 'inherit' ] ,
223235 shell : true ,
224236 windowsHide : true ,
@@ -229,6 +241,9 @@ export default class ReplayApi {
229241 } ,
230242 } ) ;
231243 this . serverProcess = child ;
244+ this . serverProcess . once ( 'exit' , ( ) => {
245+ this . serverProcess = null ;
246+ } ) ;
232247
233248 child . stdout . setEncoding ( 'utf8' ) ;
234249 const promise = await new Promise ( resolve => {
0 commit comments