Simple caching for parsed workflow and template
This commit is contained in:
@@ -91,9 +91,20 @@ export function initConnection(connection: Connection) {
|
||||
return result;
|
||||
});
|
||||
|
||||
connection.onInitialized(() => {
|
||||
if (hasWorkspaceFolderCapability) {
|
||||
connection.workspace.onDidChangeWorkspaceFolders(_event => {
|
||||
// Invalidate caches? Not sure what to do here, but we should track
|
||||
connection.console.log('Workspace folder change event received.');
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
// The content of a text document has changed. This event is emitted
|
||||
// when the text document first opened or when its content has changed.
|
||||
documents.onDidChangeContent(change => {
|
||||
clearParsedCacheEntry(change.document.uri);
|
||||
clearWorkflowTemplateCacheEntry(change.document.uri);
|
||||
return timeOperation("validation", async () => await validateTextDocument(change.document));
|
||||
});
|
||||
|
||||
@@ -119,6 +130,11 @@ export function initConnection(connection: Connection) {
|
||||
await connection.sendDiagnostics({uri: textDocument.uri, diagnostics: result});
|
||||
}
|
||||
|
||||
// connection.onDidChangeWatchedFiles(async change => {
|
||||
// // Monitored files have change in VSCode
|
||||
// connection.console.log('We received an file change event');
|
||||
// });
|
||||
|
||||
connection.onCompletion(async ({position, textDocument}: TextDocumentPositionParams): Promise<CompletionItem[]> => {
|
||||
return timeOperation(
|
||||
"completion",
|
||||
|
||||
@@ -17,7 +17,7 @@ export async function createWorkflowContext(
|
||||
if (!parsed.value) {
|
||||
throw new Error("Failed to parse workflow");
|
||||
}
|
||||
const template = await convertWorkflowTemplate(parsed.context, parsed.value);
|
||||
const template = await convertWorkflowTemplate("test.yaml", parsed.context, parsed.value);
|
||||
const context: WorkflowContext = {uri: "test.yaml", template};
|
||||
|
||||
if (job) {
|
||||
|
||||
@@ -77,7 +77,7 @@ export async function complete(
|
||||
}
|
||||
|
||||
const {token, keyToken, parent, path} = findToken(newPos, result.value);
|
||||
const template = await convertWorkflowTemplate(result.context, result.value, config?.fileProvider, {
|
||||
const template = await convertWorkflowTemplate(file.name, result.context, result.value, config?.fileProvider, {
|
||||
fetchReusableWorkflowDepth: config?.fileProvider ? 1 : 0,
|
||||
errorPolicy: ErrorPolicy.TryConversion
|
||||
});
|
||||
|
||||
@@ -19,7 +19,7 @@ export async function documentLinks(document: TextDocument): Promise<DocumentLin
|
||||
return [];
|
||||
}
|
||||
|
||||
const template = await convertWorkflowTemplate(result.context, result.value!, undefined, {
|
||||
const template = await convertWorkflowTemplate(file.name, result.context, result.value!, undefined, {
|
||||
errorPolicy: ErrorPolicy.TryConversion
|
||||
});
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ export async function hover(document: TextDocument, position: Position, config?:
|
||||
const {token, keyToken, parent} = tokenResult;
|
||||
|
||||
const tokenDefinitionInfo = (keyToken || parent || token)?.definitionInfo;
|
||||
const template = await convertWorkflowTemplate(result.context, result.value, config?.fileProvider, {
|
||||
const template = await convertWorkflowTemplate(file.name, result.context, result.value, config?.fileProvider, {
|
||||
errorPolicy: ErrorPolicy.TryConversion,
|
||||
fetchReusableWorkflowDepth: config?.fileProvider ? 1 : 0
|
||||
});
|
||||
|
||||
@@ -18,7 +18,7 @@ export async function testGetWorkflowContext(input: string): Promise<WorkflowCon
|
||||
let template: WorkflowTemplate | undefined;
|
||||
|
||||
if (result.value) {
|
||||
template = await convertWorkflowTemplate(result.context, result.value, testFileProvider, {
|
||||
template = await convertWorkflowTemplate("wf.yaml", result.context, result.value, testFileProvider, {
|
||||
fetchReusableWorkflowDepth: 1
|
||||
});
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export async function validate(textDocument: TextDocument, config?: ValidationCo
|
||||
const result: ParseWorkflowResult = parseWorkflow(file, nullTrace);
|
||||
if (result.value) {
|
||||
// Errors will be updated in the context. Attempt to do the conversion anyway in order to give the user more information
|
||||
const template = await convertWorkflowTemplate(result.context, result.value, config?.fileProvider, {
|
||||
const template = await convertWorkflowTemplate(file.name, result.context, result.value, config?.fileProvider, {
|
||||
fetchReusableWorkflowDepth: config?.fileProvider ? 1 : 0,
|
||||
errorPolicy: ErrorPolicy.TryConversion
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
`convertWorkflowTemplate` then takes that intermediate representation and converts it to a [`WorkflowTemplate`](./src/workflow-template.ts) object, which is a more convenient representation for working with workflows.
|
||||
|
||||
```typescript
|
||||
const workflowTemplate = await convertWorkflowTemplate(result.context, result.value);
|
||||
const workflowTemplate = await convertWorkflowTemplate("test.yaml", result.context, result.value);
|
||||
|
||||
// workflowTemplate.jobs[0].id === "build"
|
||||
// workflowTemplate.jobs[0].steps[0].run === "echo 'hello'"
|
||||
|
||||
@@ -11,6 +11,8 @@ import {convertReferencedWorkflow} from "./converter/referencedWorkflow";
|
||||
import {isReusableWorkflowJob} from "./type-guards";
|
||||
import {WorkflowTemplate} from "./workflow-template";
|
||||
|
||||
const workflowTemplateCache = new Map<string, WorkflowTemplate>();
|
||||
|
||||
export enum ErrorPolicy {
|
||||
ReturnErrorsOnly,
|
||||
TryConversion
|
||||
@@ -46,11 +48,17 @@ const defaultOptions: Required<WorkflowTemplateConverterOptions> = {
|
||||
};
|
||||
|
||||
export async function convertWorkflowTemplate(
|
||||
fileName: string,
|
||||
context: TemplateContext,
|
||||
root: TemplateToken,
|
||||
fileProvider?: FileProvider,
|
||||
options: WorkflowTemplateConverterOptions = defaultOptions
|
||||
): Promise<WorkflowTemplate> {
|
||||
const cachedResult = workflowTemplateCache.get(fileName)
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
const result = {} as WorkflowTemplate;
|
||||
const opts = getOptionsWithDefaults(options);
|
||||
|
||||
@@ -58,6 +66,7 @@ export async function convertWorkflowTemplate(
|
||||
result.errors = context.errors.getErrors().map(x => ({
|
||||
Message: x.message
|
||||
}));
|
||||
workflowTemplateCache.set(fileName, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -129,6 +138,7 @@ export async function convertWorkflowTemplate(
|
||||
}
|
||||
}
|
||||
|
||||
workflowTemplateCache.set(fileName, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -145,3 +155,7 @@ function getOptionsWithDefaults(options: WorkflowTemplateConverterOptions): Requ
|
||||
errorPolicy: options.errorPolicy !== undefined ? options.errorPolicy : defaultOptions.errorPolicy
|
||||
};
|
||||
}
|
||||
|
||||
export function clearWorkflowTemplateCacheEntry(uri: string) {
|
||||
workflowTemplateCache.delete(uri);
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import {File} from "./file";
|
||||
import {WORKFLOW_ROOT} from "./workflow-constants";
|
||||
import {getWorkflowSchema} from "./workflow-schema";
|
||||
import {YamlObjectReader} from "./yaml-object-reader";
|
||||
|
||||
const parsedWorkflowCache = new Map<string, ParseWorkflowResult>();
|
||||
|
||||
export interface ParseWorkflowResult {
|
||||
context: TemplateContext;
|
||||
value: TemplateToken | undefined;
|
||||
@@ -14,6 +17,11 @@ export interface ParseWorkflowResult {
|
||||
export function parseWorkflow(entryFile: File, trace: TraceWriter): ParseWorkflowResult;
|
||||
export function parseWorkflow(entryFile: File, context: TemplateContext): ParseWorkflowResult;
|
||||
export function parseWorkflow(entryFile: File, contextOrTrace: TraceWriter | TemplateContext): ParseWorkflowResult {
|
||||
const cachedResult = parsedWorkflowCache.get(entryFile.name)
|
||||
if (cachedResult) {
|
||||
return cachedResult;
|
||||
}
|
||||
|
||||
const context =
|
||||
contextOrTrace instanceof TemplateContext
|
||||
? contextOrTrace
|
||||
@@ -26,15 +34,23 @@ export function parseWorkflow(entryFile: File, contextOrTrace: TraceWriter | Tem
|
||||
for (const err of reader.errors) {
|
||||
context.error(fileId, err.message, err.range);
|
||||
}
|
||||
return {
|
||||
const result = {
|
||||
context,
|
||||
value: undefined
|
||||
};
|
||||
parsedWorkflowCache.set(entryFile.name, result);
|
||||
return result
|
||||
}
|
||||
const result = templateReader.readTemplate(context, WORKFLOW_ROOT, reader, fileId);
|
||||
const templateToken = templateReader.readTemplate(context, WORKFLOW_ROOT, reader, fileId);
|
||||
|
||||
return <ParseWorkflowResult>{
|
||||
const result = {
|
||||
context,
|
||||
value: result
|
||||
};
|
||||
value: templateToken
|
||||
} satisfies ParseWorkflowResult;
|
||||
parsedWorkflowCache.set(entryFile.name, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function clearParsedCacheEntry(path: string) {
|
||||
parsedWorkflowCache.delete(path);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user