@@ -26,36 +26,19 @@ import { startInterval, pollTransformationStatusUntilComplete } from '../../comm
2626import { CodeTransformTelemetryState } from '../../../amazonqGumby/telemetry/codeTransformTelemetryState'
2727import { convertToTimeString , isWithin30Days } from '../../../shared/datetime'
2828import { AuthUtil } from '../../util/authUtil'
29- import fs from 'fs'
29+ import fs from 'fs' // eslint-disable-line no-restricted-imports
3030import path from 'path'
3131import os from 'os'
3232import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSession'
3333import { setMaven } from './transformFileHandler'
3434
35- interface HistoryObject {
36- startTime : string
37- projectName : string
38- status : string
39- duration : string
40- diffPath : string
41- summaryPath : string
42- jobId : string
43- }
44-
4535export class TransformationHubViewProvider implements vscode . WebviewViewProvider {
4636 public static readonly viewType = 'aws.amazonq.transformationHub'
4737 private _view ?: vscode . WebviewView
4838 private lastClickedButton : string = ''
4939 private _extensionUri : vscode . Uri = globals . context . extensionUri
50- private transformationHistory : HistoryObject [ ] = [ ]
51- constructor ( ) {
52- vscode . commands . registerCommand (
53- 'aws.amazonq.transformationHub.updateContent' ,
54- ( button : 'job history' | 'plan progress' , startTime ?: number , historyFileUpdated ?: boolean ) => {
55- return this . updateContent ( button , startTime , historyFileUpdated )
56- }
57- )
58- }
40+ private transformationHistory : CodeWhispererConstants . HistoryObject [ ] = [ ]
41+ constructor ( ) { }
5942 static #instance: TransformationHubViewProvider
6043
6144 public async updateContent (
@@ -101,13 +84,13 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
10184 this . _view . webview . onDidReceiveMessage ( ( message ) => {
10285 switch ( message . command ) {
10386 case 'refreshJob' :
104- this . refreshJob ( message . jobId , message . currentStatus , message . projectName )
87+ void this . refreshJob ( message . jobId , message . currentStatus , message . projectName )
10588 break
10689 case 'openSummaryPreview' :
107- vscode . commands . executeCommand ( 'markdown.showPreview' , vscode . Uri . file ( message . filePath ) )
90+ void vscode . commands . executeCommand ( 'markdown.showPreview' , vscode . Uri . file ( message . filePath ) )
10891 break
10992 case 'openDiffFile' :
110- vscode . commands . executeCommand ( 'vscode.open' , vscode . Uri . file ( message . filePath ) )
93+ void vscode . commands . executeCommand ( 'vscode.open' , vscode . Uri . file ( message . filePath ) )
11194 break
11295 }
11396 } )
@@ -132,7 +115,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
132115 }
133116
134117 private showJobHistory ( ) : string {
135- const jobsToDisplay : HistoryObject [ ] = [ ...this . transformationHistory ]
118+ const jobsToDisplay : CodeWhispererConstants . HistoryObject [ ] = [ ...this . transformationHistory ]
136119 if ( transformByQState . isRunning ( ) ) {
137120 const current = sessionJobHistory [ transformByQState . getJobId ( ) ]
138121 jobsToDisplay . unshift ( {
@@ -202,7 +185,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
202185 </html>`
203186 }
204187
205- private getTableMarkup ( history : HistoryObject [ ] ) {
188+ private getTableMarkup ( history : CodeWhispererConstants . HistoryObject [ ] ) {
206189 return `
207190 <style>
208191 .refresh-btn {
@@ -286,16 +269,16 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
286269 transformationJobId : jobId ,
287270 profileArn : undefined ,
288271 } )
289- status = response . transformationJob . status !
272+ status = response . transformationJob . status ?? currentStatus
290273 if ( response . transformationJob . endExecutionTime && response . transformationJob . creationTime ) {
291274 duration = convertToTimeString (
292275 response . transformationJob . endExecutionTime . getTime ( ) -
293276 response . transformationJob . creationTime . getTime ( )
294277 )
295278 }
296279
297- getLogger ( ) . info (
298- 'Code Transformation: Job Id : %s\nFetched status : %s\nDuration : %s' ,
280+ getLogger ( ) . debug (
281+ 'Code Transformation: Job refresh - Fetched status for job id : %s\n{Status : %s; Duration : %s} ' ,
299282 jobId ,
300283 status ,
301284 duration
@@ -333,94 +316,34 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
333316 }
334317 transformByQState . setRefreshInProgress ( true )
335318 const messenger = transformByQState . getChatMessenger ( )
336- if ( messenger ) {
337- messenger . sendJobRefreshInProgressMessage ( ChatSessionManager . Instance . getSession ( ) . tabID ! , jobId )
338- }
319+ const tabID = ChatSessionManager . Instance . getSession ( ) . tabID
320+ messenger ? .sendJobRefreshInProgressMessage ( tabID ! , jobId )
321+ void this . updateContent ( 'job history' ) // refreshing the table disables all jobs' refresh buttons while this one is resuming
339322
340- // set state to prepare to resume job
341- transformByQState . setJobId ( jobId )
342- transformByQState . setPolledJobStatus ( status )
323+ // resume job and bring to completion
343324 try {
344- transformByQState . setJobHistoryPath ( path . join ( os . homedir ( ) , '.aws' , 'transform' , projectName , jobId ) )
345- const metadataFile = fs . readFileSync ( path . join ( transformByQState . getJobHistoryPath ( ) , 'metadata.txt' ) , {
346- encoding : 'utf8' ,
347- flag : 'r' ,
348- } )
349- const metadata = metadataFile . split ( '\t' )
350- transformByQState . setTransformationType ( metadata [ 1 ] as TransformationType )
351- transformByQState . setSourceJDKVersion ( metadata [ 2 ] as JDKVersion )
352- transformByQState . setTargetJDKVersion ( metadata [ 3 ] as JDKVersion )
353- transformByQState . setCustomDependencyVersionFilePath ( metadata [ 4 ] )
354- transformByQState . setPayloadFilePath (
355- path . join ( os . homedir ( ) , '.aws' , 'transform' , projectName , jobId , 'zipped-code.zip' )
356- )
357- setMaven ( )
358- transformByQState . setCustomBuildCommand ( metadata [ 5 ] )
359- transformByQState . setTargetJavaHome ( metadata [ 6 ] )
360- transformByQState . setProjectPath ( metadata [ 7 ] )
361- transformByQState . setStartTime ( metadata [ 8 ] )
325+ status = await this . resumeJob ( jobId , projectName , status )
362326 } catch ( e : any ) {
363- // reaching this means there was most likely a problem with the metadata file
364- getLogger ( ) . error ( 'Code Transformation: Error setting job state: %s' , ( e as Error ) . message )
327+ getLogger ( ) . error ( 'Code Transformation: Error resuming job (id: %s): %s' , jobId , ( e as Error ) . message )
365328 transformByQState . setJobDefaults ( )
366- if ( messenger ) {
367- messenger . sendJobFinishedMessage (
368- ChatSessionManager . Instance . getSession ( ) . tabID ! ,
369- CodeWhispererConstants . refreshErrorChatMessage
370- )
371- }
329+ messenger ?. sendJobFinishedMessage ( tabID ! , CodeWhispererConstants . refreshErrorChatMessage )
372330 void vscode . window . showErrorMessage ( CodeWhispererConstants . refreshErrorNotification ( jobId ) )
331+ void this . updateContent ( 'job history' )
373332 return
374333 }
375334
376- // resume polling job
377- try {
378- this . updateContent ( 'job history' ) // refreshing the table disables all jobs' refresh buttons while this one is polling
379- status = await pollTransformationStatusUntilComplete (
380- jobId ,
381- AuthUtil . instance . regionProfileManager . activeRegionProfile
382- )
383- if (
384- CodeWhispererConstants . validStatesForCheckingDownloadUrl . includes ( status ) &&
385- ! CodeWhispererConstants . failureStates . includes ( status )
386- ) {
387- duration = convertToTimeString (
388- new Date ( ) . getTime ( ) - new Date ( transformByQState . getStartTime ( ) ) . getTime ( )
389- )
390- jobHistoryPath = await this . retrieveArtifacts ( jobId , projectName )
391- // delete payload and metadata files
392- if ( transformByQState . getPayloadFilePath ( ) ) {
393- fs . rmSync ( transformByQState . getPayloadFilePath ( ) , { force : true } )
394- }
395- fs . rmSync ( path . join ( transformByQState . getJobHistoryPath ( ) , 'metadata.txt' ) , { force : true } )
396- // delete temporary build logs file
397- const logFilePath = path . join ( os . tmpdir ( ) , 'build-logs.txt' )
398- if ( fs . existsSync ( logFilePath ) ) {
399- fs . rmSync ( logFilePath , { force : true } )
400- }
401- }
402- } catch ( e : any ) {
403- getLogger ( ) . error ( 'Code Transformation: Error resuming job (id: %s): %s' , jobId , ( e as Error ) . message )
404- transformByQState . setJobDefaults ( )
405- if ( messenger ) {
406- messenger . sendJobFinishedMessage (
407- ChatSessionManager . Instance . getSession ( ) . tabID ! ,
408- CodeWhispererConstants . refreshErrorChatMessage
409- )
410- }
411- void vscode . window . showErrorMessage ( CodeWhispererConstants . refreshErrorNotification ( jobId ) )
412- this . updateContent ( 'job history' ) // re-enable refresh buttons
413- return
335+ // download artifacts if available
336+ if (
337+ CodeWhispererConstants . validStatesForCheckingDownloadUrl . includes ( status ) &&
338+ ! CodeWhispererConstants . failureStates . includes ( status )
339+ ) {
340+ duration = convertToTimeString ( Date . now ( ) - new Date ( transformByQState . getStartTime ( ) ) . getTime ( ) )
341+ jobHistoryPath = await this . retrieveArtifacts ( jobId , projectName )
414342 }
415343
416344 // reset state
417345 transformByQState . setJobDefaults ( )
418- if ( messenger ) {
419- messenger . sendJobFinishedMessage (
420- ChatSessionManager . Instance . getSession ( ) . tabID ! ,
421- CodeWhispererConstants . refreshCompletedChatMessage
422- )
423- }
346+ messenger ?. sendJobFinishedMessage ( tabID ! , CodeWhispererConstants . refreshCompletedChatMessage )
424347 } else {
425348 // FAILED or STOPPED job
426349 getLogger ( ) . info ( 'Code Transformation: No artifacts available to download (job status = %s)' , status )
@@ -472,10 +395,8 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
472395 } catch ( error ) {
473396 jobHistoryPath = ''
474397 } finally {
475- if ( fs . existsSync ( resultsPath ) ) {
476- fs . rmSync ( resultsPath , { recursive : true , force : true } )
477- }
478- getLogger ( ) . info ( 'Code Transformation: Deleted temporary extraction directory' )
398+ // delete temporary extraction directory
399+ fs . rmSync ( resultsPath , { recursive : true , force : true } )
479400 }
480401 }
481402 return jobHistoryPath
@@ -489,7 +410,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
489410 const jobs = historyFile . split ( '\n' )
490411 jobs . shift ( ) // removes headers
491412 if ( jobs . length > 0 ) {
492- jobs . forEach ( ( job ) => {
413+ for ( const job of jobs ) {
493414 if ( job ) {
494415 const jobInfo = job . split ( '\t' )
495416 // startTime: jobInfo[0], projectName: jobInfo[1], status: jobInfo[2], duration: jobInfo[3], diffPath: jobInfo[4], summaryPath: jobInfo[5], jobId: jobInfo[6]
@@ -506,7 +427,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
506427 }
507428 history . push ( jobInfo )
508429 }
509- } )
430+ }
510431 }
511432 }
512433 if ( history . length > 0 ) {
@@ -520,6 +441,50 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
520441 }
521442 }
522443
444+ private async resumeJob ( jobId : string , projectName : string , status : string ) {
445+ // set state to prepare to resume job
446+ await this . setupTransformationState ( jobId , projectName , status )
447+ // resume polling the job
448+ return await this . pollAndCompleteTransformation ( jobId )
449+ }
450+
451+ private async setupTransformationState ( jobId : string , projectName : string , status : string ) {
452+ transformByQState . setJobId ( jobId )
453+ transformByQState . setPolledJobStatus ( status )
454+ transformByQState . setJobHistoryPath ( path . join ( os . homedir ( ) , '.aws' , 'transform' , projectName , jobId ) )
455+ const metadataFile = fs . readFileSync ( path . join ( transformByQState . getJobHistoryPath ( ) , 'metadata.txt' ) , {
456+ encoding : 'utf8' ,
457+ flag : 'r' ,
458+ } )
459+ const metadata = metadataFile . split ( '\t' )
460+ transformByQState . setTransformationType ( metadata [ 1 ] as TransformationType )
461+ transformByQState . setSourceJDKVersion ( metadata [ 2 ] as JDKVersion )
462+ transformByQState . setTargetJDKVersion ( metadata [ 3 ] as JDKVersion )
463+ transformByQState . setCustomDependencyVersionFilePath ( metadata [ 4 ] )
464+ transformByQState . setPayloadFilePath (
465+ path . join ( os . homedir ( ) , '.aws' , 'transform' , projectName , jobId , 'zipped-code.zip' )
466+ )
467+ setMaven ( )
468+ transformByQState . setCustomBuildCommand ( metadata [ 5 ] )
469+ transformByQState . setTargetJavaHome ( metadata [ 6 ] )
470+ transformByQState . setProjectPath ( metadata [ 7 ] )
471+ transformByQState . setStartTime ( metadata [ 8 ] )
472+ }
473+
474+ private async pollAndCompleteTransformation ( jobId : string ) {
475+ const status = await pollTransformationStatusUntilComplete (
476+ jobId ,
477+ AuthUtil . instance . regionProfileManager . activeRegionProfile
478+ )
479+ // delete payload and metadata files
480+ fs . rmSync ( transformByQState . getPayloadFilePath ( ) , { force : true } )
481+ fs . rmSync ( path . join ( transformByQState . getJobHistoryPath ( ) , 'metadata.txt' ) , { force : true } )
482+ // delete temporary build logs file
483+ const logFilePath = path . join ( os . tmpdir ( ) , 'build-logs.txt' )
484+ fs . rmSync ( logFilePath , { force : true } )
485+ return status
486+ }
487+
523488 private generateTransformationStepMarkup (
524489 name : string ,
525490 startTime : Date | undefined ,
@@ -928,8 +893,8 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
928893 }
929894}
930895
931- export function readHistoryFile ( ) : HistoryObject [ ] {
932- const history : HistoryObject [ ] = [ ]
896+ export function readHistoryFile ( ) : CodeWhispererConstants . HistoryObject [ ] {
897+ const history : CodeWhispererConstants . HistoryObject [ ] = [ ]
933898 const jobHistoryFilePath = path . join ( os . homedir ( ) , '.aws' , 'transform' , 'transformation_history.tsv' )
934899 if ( fs . existsSync ( jobHistoryFilePath ) ) {
935900 const historyFile = fs . readFileSync ( jobHistoryFilePath , { encoding : 'utf8' , flag : 'r' } )
0 commit comments