@@ -41,6 +41,7 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
4141 // Fetch sessionId from snapshot options if present
4242 const sessionId = snapshot ?. options ?. sessionId ;
4343 let capsBuildId = ''
44+ const contextId = snapshot ?. options ?. contextId ;
4445
4546 if ( sessionId ) {
4647 // Check if sessionId exists in the map
@@ -71,7 +72,23 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
7172 }
7273
7374 ctx . testType = testType ;
74- ctx . snapshotQueue ?. enqueue ( snapshot ) ;
75+
76+ if ( contextId && ! ctx . contextToSnapshotMap ) {
77+ ctx . contextToSnapshotMap = new Map ( ) ;
78+ ctx . log . debug ( `Initialized empty context mapping map for contextId: ${ contextId } ` ) ;
79+ }
80+
81+ if ( contextId && ctx . contextToSnapshotMap ) {
82+ ctx . contextToSnapshotMap . set ( contextId , 0 ) ;
83+ ctx . log . debug ( `Marking contextId as captured and added to queue: ${ contextId } ` ) ;
84+ }
85+
86+ if ( contextId ) {
87+ ctx . snapshotQueue ?. enqueueFront ( snapshot ) ;
88+ } else {
89+ ctx . snapshotQueue ?. enqueue ( snapshot ) ;
90+ }
91+
7592 ctx . isSnapshotCaptured = true ;
7693 replyCode = 200 ;
7794 replyBody = { data : { message : "success" , warnings : [ ] } } ;
@@ -130,7 +147,113 @@ export default async (ctx: Context): Promise<FastifyInstance<Server, IncomingMes
130147 reply . code ( 200 ) . send ( { status : 'Server is running' , version : ctx . cliVersion } ) ;
131148 } ) ;
132149
133-
150+ // Get snapshot status
151+ server . get ( '/snapshot/status' , opts , async ( request , reply ) => {
152+ let replyCode : number ;
153+ let replyBody : Record < string , any > ;
154+
155+
156+ try {
157+ ctx . log . debug ( `request.query : ${ JSON . stringify ( request . query ) } ` ) ;
158+ const { contextId, pollTimeout, snapshotName } = request . query as { contextId : string , pollTimeout : number , snapshotName : string } ;
159+ if ( ! contextId || ! snapshotName ) {
160+ throw new Error ( 'contextId and snapshotName are required parameters' ) ;
161+ }
162+
163+ const timeoutDuration = pollTimeout * 1000 || 30000 ;
164+
165+ // Check if we have stored snapshot status for this contextId
166+ if ( ctx . contextToSnapshotMap ?. has ( contextId ) ) {
167+ let contextStatus = ctx . contextToSnapshotMap . get ( contextId ) ;
168+
169+ while ( contextStatus == 0 ) {
170+ // Wait 5 seconds before next check
171+ await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
172+
173+ contextStatus = ctx . contextToSnapshotMap . get ( contextId ) ;
174+ }
175+
176+ if ( contextStatus == 2 ) {
177+ throw new Error ( "Snapshot Failed" ) ;
178+ }
179+
180+ ctx . log . debug ( "Snapshot uploaded successfully" ) ;
181+
182+ // Poll external API until it returns 200 or timeout is reached
183+ let lastExternalResponse : any = null ;
184+ const startTime = Date . now ( ) ;
185+
186+ while ( true ) {
187+ try {
188+ const externalResponse = await ctx . client . getSnapshotStatus (
189+ snapshotName ,
190+ contextId ,
191+ ctx
192+ ) ;
193+
194+ lastExternalResponse = externalResponse ;
195+
196+ if ( externalResponse . statusCode === 200 ) {
197+ replyCode = 200 ;
198+ replyBody = externalResponse . data ;
199+ return reply . code ( replyCode ) . send ( replyBody ) ;
200+ } else if ( externalResponse . statusCode === 202 ) {
201+ replyBody = externalResponse . data ;
202+ ctx . log . debug ( `External API attempt: Still processing, Pending Screenshots ${ externalResponse . snapshotCount } ` ) ;
203+ await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
204+ } else if ( externalResponse . statusCode === 404 ) {
205+ ctx . log . debug ( `Snapshot still processing, not uploaded` ) ;
206+ await new Promise ( resolve => setTimeout ( resolve , 5000 ) ) ;
207+ } else {
208+ ctx . log . debug ( `Unexpected response from external API: ${ JSON . stringify ( externalResponse ) } ` ) ;
209+ replyCode = 500 ;
210+ replyBody = {
211+ error : {
212+ message : `Unexpected response from external API: ${ externalResponse . statusCode } ` ,
213+ externalApiStatus : externalResponse . statusCode
214+ }
215+ } ;
216+ return reply . code ( replyCode ) . send ( replyBody ) ;
217+ }
218+
219+ ctx . log . debug ( `timeoutDuration: ${ timeoutDuration } ` ) ;
220+ ctx . log . debug ( `Time passed: ${ Date . now ( ) - startTime } ` ) ;
221+
222+ if ( Date . now ( ) - startTime > timeoutDuration ) {
223+ replyCode = 202 ;
224+ replyBody = {
225+ data : {
226+ message : 'Request timed out-> Snapshot still processing'
227+ }
228+ } ;
229+ return reply . code ( replyCode ) . send ( replyBody ) ;
230+ }
231+
232+ } catch ( externalApiError : any ) {
233+ ctx . log . debug ( `External API call failed: ${ externalApiError . message } ` ) ;
234+ replyCode = 500 ;
235+ replyBody = {
236+ error : {
237+ message : `External API call failed: ${ externalApiError . message } `
238+ }
239+ } ;
240+ return reply . code ( replyCode ) . send ( replyBody ) ;
241+ }
242+ }
243+ } else {
244+ // No snapshot found for this contextId
245+ replyCode = 404 ;
246+ replyBody = { error : { message : `No snapshot found for contextId: ${ contextId } ` } } ;
247+ return reply . code ( replyCode ) . send ( replyBody ) ;
248+ }
249+ } catch ( error : any ) {
250+ ctx . log . debug ( `snapshot status failed; ${ error } ` ) ;
251+ replyCode = 500 ;
252+ replyBody = { error : { message : error . message } } ;
253+ return reply . code ( replyCode ) . send ( replyBody ) ;
254+ }
255+ } ) ;
256+
134257
135258 await server . listen ( { port : ctx . options . port } ) ;
136259 // store server's address for SDK
0 commit comments