Skip to content

Commit ef286fb

Browse files
yaythomasSimon Levett
andauthored
fix(stepfunctions): offline sfn visualizer (#3485)
Step Functions Render Graph visualizer will now work offline, as long as there is a cached local copy of the generating js and css files. Closes #2922. There is now a graceful fallback when internet connectivity isn't available to a c9 or vscode host but where the required files are available in the local filesystem cache (either by previous automatic caching, or by manual user intervention). Implementation avoids confusing the return type of 'updateCache' or 'updateCachedFile' and instead only checks for local files after a updateCache call fails. Includes unit tests. Includes changelog. This commit merges 3 previous work in progress commits. With thanks for original work by: Author: Simon Levett <[email protected]> Date: Thu Jan 12 20:05:02 2023 +1100 Co-authored-by: Simon Levett <[email protected]>
1 parent 6d7bbd0 commit ef286fb

File tree

5 files changed

+75
-2
lines changed

5 files changed

+75
-2
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"type": "Bug Fix",
3+
"description": "Add fallback to local cached files for Step Function Visualizations where host doesn't have internet."
4+
}

src/stepFunctions/commands/visualizeStateMachine/abstractAslVisualizationManager.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,14 @@ export abstract class AbstractAslVisualizationManager<T extends AslVisualization
5656
protected getExistingVisualization(key: string): T | undefined {
5757
return this.managedVisualizations.get(key)
5858
}
59+
60+
protected async updateCache(globalStorage: vscode.Memento, logger: Logger): Promise<void> {
61+
try {
62+
await this.cache.updateCache(globalStorage)
63+
} catch (err) {
64+
// So we can't update the cache, but can we use an existing on disk version.
65+
logger.warn('Updating State Machine Graph Visualisation assets failed, checking for fallback local cache.')
66+
await this.cache.confirmCacheExists()
67+
}
68+
}
5969
}

src/stepFunctions/commands/visualizeStateMachine/aslVisualizationManager.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,7 @@ export class AslVisualizationManager extends AbstractAslVisualizationManager {
3333

3434
// Existing visualization does not exist, construct new visualization
3535
try {
36-
await this.cache.updateCache(globalStorage)
37-
36+
await this.updateCache(globalStorage, logger)
3837
const newVisualization = new AslVisualization(document)
3938
this.handleNewVisualization(document.uri.fsPath, newVisualization)
4039

src/stepFunctions/utils.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,30 @@ export class StateMachineGraphCache {
117117
}
118118
}
119119

120+
// Coordinates check for multiple cached files.
121+
public async confirmCacheExists(): Promise<boolean> {
122+
const cssExists = await this.fileExists(this.cssFilePath)
123+
const jsExists = await this.fileExists(this.jsFilePath)
124+
125+
if (cssExists && jsExists) {
126+
return true
127+
}
128+
129+
if (!cssExists) {
130+
// Help users setup on disconnected C9/VSCode instances.
131+
this.logger.error(
132+
`Failed to locate cached State Machine Graph css assets. Expected to find: "${visualizationCssUrl}" at "${this.cssFilePath}"`
133+
)
134+
}
135+
if (!jsExists) {
136+
// Help users setup on disconnected C9/VSCode instances.
137+
this.logger.error(
138+
`Failed to locate cached State Machine Graph js assets. Expected to find: "${visualizationScriptUrl}" at "${this.jsFilePath}"`
139+
)
140+
}
141+
throw new Error('Failed to located cached State Machine Graph assets')
142+
}
143+
120144
protected async writeToLocalStorage(destinationPath: string, data: string): Promise<void> {
121145
const storageFolder = this.dirPath
122146

src/test/stepFunctions/utils.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,42 @@ describe('StateMachineGraphCache', function () {
122122
assert.ok(globalStorage.update.notCalled)
123123
assert.ok(writeFile.notCalled)
124124
})
125+
it('it passes if both files required exist', async function () {
126+
const getFileData = sinon.stub().resolves(true)
127+
const fileExists = sinon.stub().resolves(true)
128+
129+
const writeFile = sinon.spy()
130+
131+
const cache = new StateMachineGraphCache({
132+
getFileData,
133+
fileExists,
134+
writeFile,
135+
cssFilePath: '',
136+
jsFilePath: '',
137+
dirPath: '',
138+
})
139+
140+
await cache.confirmCacheExists()
141+
142+
assert.ok(fileExists.calledTwice)
143+
})
144+
it('it rejects if both files required do not exist on filesystem', async function () {
145+
const getFileData = sinon.stub()
146+
const fileExists = sinon.stub().onFirstCall().resolves(true).onSecondCall().resolves(false)
147+
148+
const writeFile = sinon.spy()
149+
150+
const cache = new StateMachineGraphCache({
151+
getFileData,
152+
fileExists,
153+
writeFile,
154+
cssFilePath: 'one',
155+
jsFilePath: 'two',
156+
dirPath: '',
157+
})
158+
159+
assert.rejects(cache.confirmCacheExists())
160+
})
125161

126162
it('creates assets directory when it does not exist', async function () {
127163
const globalStorage = {

0 commit comments

Comments
 (0)