Skip to content

Commit 76d8902

Browse files
committed
Change job history table file reading logic - store array, read file less often, limit table to 10 rows and validate dates
1 parent 25d0c6f commit 76d8902

File tree

4 files changed

+89
-77
lines changed

4 files changed

+89
-77
lines changed

packages/core/src/amazonqGumby/activation.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import { setContext } from '../shared/vscode/setContext'
2121
export async function activate(context: ExtContext) {
2222
void setContext('gumby.wasQCodeTransformationUsed', false)
2323

24-
const transformationHubViewProvider = new TransformationHubViewProvider()
24+
const transformationHubViewProvider = TransformationHubViewProvider.instance
2525
new ProposedTransformationExplorer(context.extensionContext)
2626
// Register an activation event listener to determine when the IDE opens, closes or users
2727
// select to open a new workspace

packages/core/src/codewhisperer/commands/startTransformByQ.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ import { convertDateToTimestamp } from '../../shared/datetime'
7979
import { findStringInDirectory } from '../../shared/utilities/workspaceUtils'
8080
import { makeTemporaryToolkitFolder } from '../../shared/filesystemUtilities'
8181
import { AuthUtil } from '../util/authUtil'
82+
import { updateHistoryTable } from '../service/transformByQ/transformationHubViewProvider'
8283

8384
export function getFeedbackCommentData() {
8485
const jobId = transformByQState.getJobId()
@@ -802,6 +803,7 @@ export async function postTransformationJob() {
802803

803804
const jobDetails = fields.join('\t') + '\n'
804805
fs.writeFileSync(historyLogFilePath, jobDetails, { flag: 'a' })
806+
await updateHistoryTable(true)
805807
}
806808
}
807809

packages/core/src/codewhisperer/service/transformByQ/transformFileHandler.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ import { AbsolutePathDetectedError } from '../../../amazonqGumby/errors'
1717
import { getLogger } from '../../../shared/logger/logger'
1818
import AdmZip from 'adm-zip'
1919
import { IManifestFile } from './humanInTheLoopManager'
20+
import { HistoryObject } from './transformationHubViewProvider'
21+
import { isWithin30Days } from '../../../shared/datetime'
2022

2123
export async function getDependenciesFolderInfo(): Promise<FolderInfo> {
2224
const dependencyFolderName = `${CodeWhispererConstants.dependencyFolderName}${globals.clock.Date.now()}`
@@ -182,6 +184,34 @@ export async function openBuildLogFile() {
182184
await vscode.window.showTextDocument(doc)
183185
}
184186

187+
export function readHistoryFile(): HistoryObject[] {
188+
const history: HistoryObject[] = []
189+
const jobHistoryFilePath = path.join(os.homedir(), '.aws', 'transform', 'transformation-history.tsv')
190+
if (existsSync(jobHistoryFilePath)) {
191+
const historyFile = readFileSync(jobHistoryFilePath, { encoding: 'utf8', flag: 'r' })
192+
const jobs = historyFile.split('\n')
193+
jobs.shift() // removes headers
194+
195+
// Process from end, stop at 10 valid entries
196+
for (let i = jobs.length - 1; i >= 0 && history.length < 10; i--) {
197+
const job = jobs[i]
198+
if (job && isWithin30Days(job.split('\t')[0])) {
199+
const jobInfo = job.split('\t')
200+
history.push({
201+
startTime: jobInfo[0],
202+
projectName: jobInfo[1],
203+
status: jobInfo[2],
204+
duration: jobInfo[3],
205+
diffPath: jobInfo[4],
206+
summaryPath: jobInfo[5],
207+
jobId: jobInfo[6],
208+
})
209+
}
210+
}
211+
}
212+
return history
213+
}
214+
185215
export async function createPomCopy(
186216
dirname: string,
187217
pomFileVirtualFileReference: vscode.Uri,

packages/core/src/codewhisperer/service/transformByQ/transformationHubViewProvider.ts

Lines changed: 56 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,40 @@ import fs from 'fs'
3030
import path from 'path'
3131
import os from 'os'
3232
import { ChatSessionManager } from '../../../amazonqGumby/chat/storages/chatSession'
33+
import { setMaven, readHistoryFile } from './transformFileHandler'
34+
35+
export 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+
45+
export async function updateHistoryTable(historyFileUpdated?: boolean) {
46+
await TransformationHubViewProvider.instance.updateContent('job history', undefined, historyFileUpdated)
47+
}
3348

3449
export class TransformationHubViewProvider implements vscode.WebviewViewProvider {
3550
public static readonly viewType = 'aws.amazonq.transformationHub'
3651
private _view?: vscode.WebviewView
3752
private lastClickedButton: string = ''
3853
private _extensionUri: vscode.Uri = globals.context.extensionUri
54+
private transformationHistory: HistoryObject[] = []
3955
constructor() {}
4056
static #instance: TransformationHubViewProvider
4157

4258
public async updateContent(
4359
button: 'job history' | 'plan progress',
44-
startTime: number = CodeTransformTelemetryState.instance.getStartTime()
60+
startTime: number = CodeTransformTelemetryState.instance.getStartTime(),
61+
historyFileUpdated?: boolean
4562
) {
4663
this.lastClickedButton = button
64+
if (historyFileUpdated) {
65+
this.transformationHistory = readHistoryFile()
66+
}
4767
if (this._view) {
4868
if (this.lastClickedButton === 'job history') {
4969
clearInterval(transformByQState.getIntervalId())
@@ -94,6 +114,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
94114
localResourceRoots: [this._extensionUri],
95115
}
96116

117+
this.transformationHistory = readHistoryFile()
97118
if (this.lastClickedButton === 'job history') {
98119
this._view!.webview.html = this.showJobHistory()
99120
} else {
@@ -108,41 +129,10 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
108129
}
109130

110131
private showJobHistory(): string {
111-
const history: {
112-
startTime: string
113-
projectName: string
114-
status: string
115-
duration: string
116-
diffPath: string
117-
summaryPath: string
118-
jobId: string
119-
}[] = []
120-
const jobHistoryFilePath = path.join(os.homedir(), '.aws', 'transform', 'transformation-history.tsv')
121-
if (fs.existsSync(jobHistoryFilePath)) {
122-
const historyFile = fs.readFileSync(jobHistoryFilePath, { encoding: 'utf8', flag: 'r' })
123-
const jobs = historyFile.split('\n')
124-
jobs.shift() // removes headers
125-
if (jobs.length > 0) {
126-
jobs.forEach((job) => {
127-
if (job) {
128-
const jobInfo = job.split('\t')
129-
const jobObject = {
130-
startTime: jobInfo[0],
131-
projectName: jobInfo[1],
132-
status: jobInfo[2],
133-
duration: jobInfo[3],
134-
diffPath: jobInfo[4],
135-
summaryPath: jobInfo[5],
136-
jobId: jobInfo[6],
137-
}
138-
history.push(jobObject)
139-
}
140-
})
141-
}
142-
}
132+
const jobsToDisplay: HistoryObject[] = [...this.transformationHistory]
143133
if (transformByQState.isRunning()) {
144134
const current = sessionJobHistory[transformByQState.getJobId()]
145-
history.push({
135+
jobsToDisplay.unshift({
146136
startTime: current.startTime,
147137
projectName: current.projectName,
148138
status: current.status,
@@ -152,7 +142,6 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
152142
jobId: transformByQState.getJobId(),
153143
})
154144
}
155-
history.reverse() // to show in descending order, chronologically
156145
return `<!DOCTYPE html>
157146
<html lang="en">
158147
<head>
@@ -165,14 +154,14 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
165154
</head>
166155
<body>
167156
<p><b>Transformation History</b></p>
168-
<p>This table lists the jobs that you have run in the past 30 days.
157+
<p>This table lists the most recent jobs that you have run in the past 30 days.
169158
To open the diff patch and summary files, choose the provided links. To get an updated job status, choose the refresh icon.
170159
The diff path and summary will appear once they are available.
171160
</p>
172161
${
173-
history.length === 0
162+
jobsToDisplay.length === 0
174163
? `<p>${CodeWhispererConstants.nothingToShowMessage}</p>`
175-
: this.getTableMarkup(history)
164+
: this.getTableMarkup(jobsToDisplay)
176165
}
177166
<script>
178167
const vscode = acquireVsCodeApi();
@@ -213,17 +202,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
213202
</html>`
214203
}
215204

216-
private getTableMarkup(
217-
history: {
218-
startTime: string
219-
projectName: string
220-
status: string
221-
duration: string
222-
diffPath: string
223-
summaryPath: string
224-
jobId: string
225-
}[]
226-
) {
205+
private getTableMarkup(history: HistoryObject[]) {
227206
return `
228207
<style>
229208
.refresh-btn {
@@ -301,33 +280,33 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
301280
// fetch status from server
302281
let status = ''
303282
let duration = ''
304-
try {
305-
const response = await codeWhispererClient.codeModernizerGetCodeTransformation({
306-
transformationJobId: jobId,
307-
profileArn: undefined,
308-
})
309-
status = response.transformationJob.status!
310-
if (response.transformationJob.endExecutionTime && response.transformationJob.creationTime) {
311-
duration = convertToTimeString(
312-
response.transformationJob.endExecutionTime.getTime() -
313-
response.transformationJob.creationTime.getTime()
314-
)
315-
}
283+
if (currentStatus === 'COMPLETED' || currentStatus === 'PARTIALLY_COMPLETED') {
284+
// job is already completed, no need to fetch status
285+
status = currentStatus
286+
} else {
287+
try {
288+
const response = await codeWhispererClient.codeModernizerGetCodeTransformation({
289+
transformationJobId: jobId,
290+
profileArn: undefined,
291+
})
292+
status = response.transformationJob.status!
293+
if (response.transformationJob.endExecutionTime && response.transformationJob.creationTime) {
294+
duration = convertToTimeString(
295+
response.transformationJob.endExecutionTime.getTime() -
296+
response.transformationJob.creationTime.getTime()
297+
)
298+
}
316299

317-
console.log('status returned: %s', status)
318-
console.log('duration returned: %s', duration)
319-
} catch (error) {
320-
console.error('error fetching status: %s', (error as Error).message)
321-
return
300+
console.log('status returned: %s\nduration returned: %s', status, duration)
301+
} catch (error) {
302+
console.error('error fetching status: %s', (error as Error).message)
303+
return
304+
}
322305
}
323306

324307
// retrieve artifacts and updated duration if available
325308
let jobHistoryPath: string = ''
326-
if (
327-
CodeWhispererConstants.validStatesForCheckingDownloadUrl.includes(status) &&
328-
!CodeWhispererConstants.failureStates.includes(status)
329-
) {
330-
// status is COMPLETED or PARTIALLY_COMPLETED on server side
309+
if (status === 'COMPLETED' || status === 'PARTIALLY_COMPLETED') {
331310
console.log('valid successful status')
332311

333312
// artifacts should be available to download
@@ -363,7 +342,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
363342
transformByQState.setPayloadFilePath(
364343
path.join(os.homedir(), '.aws', 'transform', projectName, jobId, 'zipped-code.zip')
365344
)
366-
transformByQState.setMavenName('mvn')
345+
setMaven()
367346
transformByQState.setCustomBuildCommand(metadata[5])
368347
transformByQState.setTargetJavaHome(metadata[6])
369348
transformByQState.setProjectPath(metadata[7])
@@ -388,7 +367,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
388367

389368
// resume polling job
390369
try {
391-
this.updateContent('job history') // refreshing the table disables all jobs' refresh buttons while this one is polling
370+
updateHistoryTable() // refreshing the table disables all jobs' refresh buttons while this one is polling
392371
status = await pollTransformationStatusUntilComplete(
393372
jobId,
394373
AuthUtil.instance.regionProfileManager.activeRegionProfile
@@ -426,6 +405,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
426405
// just show notification
427406
void vscode.window.showErrorMessage(`There was an error refreshing this job. Job Id: ${jobId}`)
428407
}
408+
updateHistoryTable() // re-enable refresh buttons
429409
return
430410
}
431411

@@ -453,7 +433,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
453433
}
454434

455435
// update local file and history table
456-
this.updateHistoryFile(status, duration, jobHistoryPath, jobId)
436+
await this.updateHistoryFile(status, duration, jobHistoryPath, jobId)
457437
}
458438

459439
private async retrieveArtifacts(jobId: string, projectName: string) {
@@ -493,7 +473,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
493473
return jobHistoryPath
494474
}
495475

496-
private updateHistoryFile(status: string, duration: string, jobHistoryPath: string, jobId: string) {
476+
private async updateHistoryFile(status: string, duration: string, jobHistoryPath: string, jobId: string) {
497477
const history: string[][] = []
498478
const historyLogFilePath = path.join(os.homedir(), '.aws', 'transform', 'transformation-history.tsv')
499479
if (fs.existsSync(historyLogFilePath)) {
@@ -528,7 +508,7 @@ export class TransformationHubViewProvider implements vscode.WebviewViewProvider
528508
fs.writeFileSync(historyLogFilePath, tsvContent, { flag: 'a' })
529509

530510
// update table content
531-
this.updateContent('job history')
511+
await updateHistoryTable(true)
532512
}
533513
}
534514

0 commit comments

Comments
 (0)