Skip to content

Commit

Permalink
Decrease input-lag for large queries (#158)
Browse files Browse the repository at this point in the history
* proof of concept

* merge main

* works again

* fix overuse of main channel

* mellan

* tests work

* fix worker thread for node as well

* self review

* self review

* self review

* fix build

* tests

* fix e2e test

* merge semantic analsysis and syntax errors again

* review comments

* self review

* fix tests

* worker pool-ish for vscode

* smarter 'pool' mgmt

* kindaworks

* works

* cleanup new parser adapter

* restore pkg json

* workerpool

* worker pool for client as well

* cleanup workers

* fix errors

* fix tests

* fix todos

* fix build

* test-are-green

* works for vite

* fixlint

* self review

* re-add proper build

* fix input lag even when parse is fast

* add changeset

* fix e2e test

* pr comments
  • Loading branch information
OskarDamkjaer committed Jan 30, 2024
1 parent 7768efd commit 1e210cb
Show file tree
Hide file tree
Showing 27 changed files with 627 additions and 239 deletions.
9 changes: 9 additions & 0 deletions .changeset/pink-chefs-trade.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@neo4j-cypher/react-codemirror-playground': patch
'@neo4j-cypher/language-support': patch
'@neo4j-cypher/react-codemirror': patch
'neo4j-cypher-vscode-extension': patch
'@neo4j-cypher/language-server': patch
---

Moves semantic analysis to a separate worker file
89 changes: 71 additions & 18 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion packages/language-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
},
"dependencies": {
"@neo4j-cypher/language-support": "2.0.0-next.2",
"lodash.debounce": "^4.0.8",
"neo4j-driver": "^5.3.0",
"vscode-languageserver": "^8.1.0",
"vscode-languageserver-textdocument": "^1.0.8"
"vscode-languageserver-textdocument": "^1.0.8",
"workerpool": "^9.0.4"
},
"scripts": {
"build": "tsc -b && npm run bundle && npm run make-executable",
Expand All @@ -47,6 +49,7 @@
"watch": "tsc -b -w"
},
"devDependencies": {
"@types/lodash.debounce": "^4.0.9",
"esbuild": "^0.19.4"
}
}
14 changes: 14 additions & 0 deletions packages/language-server/src/lint-worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { validateSemantics } from '@neo4j-cypher/language-support';
import workerpool from 'workerpool';

workerpool.worker({ validateSemantics });

type LinterArgs = Parameters<typeof validateSemantics>;

export type LinterTask = workerpool.Promise<
ReturnType<typeof validateSemantics>
>;

export type LintWorker = {
validateSemantics: (...args: LinterArgs) => LinterTask;
};
63 changes: 63 additions & 0 deletions packages/language-server/src/linting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {
findEndPosition,
parserWrapper,
validateSyntax,
} from '@neo4j-cypher/language-support';
import debounce from 'lodash.debounce';
import { join } from 'path';
import { Diagnostic, TextDocumentChangeEvent } from 'vscode-languageserver';
import { TextDocument } from 'vscode-languageserver-textdocument';
import workerpool from 'workerpool';
import { LinterTask, LintWorker } from './lint-worker';

const pool = workerpool.pool(join(__dirname, 'lint-worker.js'), {
minWorkers: 2,
workerTerminateTimeout: 2000,
});

let lastSemanticJob: LinterTask | undefined;

async function rawLintDocument(
change: TextDocumentChangeEvent<TextDocument>,
sendDiagnostics: (diagnostics: Diagnostic[]) => void,
) {
const { document } = change;

const query = document.getText();
if (query.length === 0) {
return;
}

const syntaxErrors = validateSyntax(query, {});

sendDiagnostics(syntaxErrors);

if (syntaxErrors.length === 0) {
try {
if (lastSemanticJob !== undefined && !lastSemanticJob.resolved) {
void lastSemanticJob.cancel();
}

const proxyWorker = (await pool.proxy()) as unknown as LintWorker;
lastSemanticJob = proxyWorker.validateSemantics(query);
const result = await lastSemanticJob;

sendDiagnostics(
result.map((el) => findEndPosition(el, parserWrapper.parsingResult)),
);
} catch (err) {
if (!(err instanceof workerpool.Promise.CancellationError)) {
console.error(err);
}
}
}
}

export const lintDocument = debounce(rawLintDocument, 600, {
leading: false,
trailing: true,
});

export const cleanupWorkers = () => {
void pool.terminate();
};
33 changes: 17 additions & 16 deletions packages/language-server/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
createConnection,
Diagnostic,
DidChangeConfigurationNotification,
InitializeResult,
ProposedFeatures,
Expand All @@ -11,10 +12,7 @@ import {

import { TextDocument } from 'vscode-languageserver-textdocument';

import {
syntaxColouringLegend,
validateSyntax,
} from '@neo4j-cypher/language-support';
import { syntaxColouringLegend } from '@neo4j-cypher/language-support';
import { Neo4jSchemaPoller } from '@neo4j-cypher/schema-poller';
import { doAutoCompletion } from './autocompletion';
import { doSignatureHelp } from './signatureHelp';
Expand All @@ -23,6 +21,8 @@ import { Neo4jSettings } from './types';

const connection = createConnection(ProposedFeatures.all);

import { cleanupWorkers, lintDocument } from './linting';

// Create a simple text document manager.
const documents: TextDocuments<TextDocument> = new TextDocuments(TextDocument);

Expand Down Expand Up @@ -73,18 +73,14 @@ connection.onInitialized(() => {
);
});

// Trigger the syntactic errors highlighting on every document change
documents.onDidChangeContent((change) => {
const document = change.document;
const diagnostics = validateSyntax(
document.getText(),
neo4jSdk.metadata?.dbSchema ?? {},
);
void connection.sendDiagnostics({
uri: document.uri,
diagnostics: diagnostics,
});
});
documents.onDidChangeContent((change) =>
lintDocument(change, (diagnostics: Diagnostic[]) => {
void connection.sendDiagnostics({
uri: change.document.uri,
diagnostics,
});
}),
);

// Trigger the syntax colouring
connection.languages.semanticTokens.on(
Expand Down Expand Up @@ -121,4 +117,9 @@ connection.onDidChangeConfiguration(
);

documents.listen(connection);

connection.listen();

connection.onExit(() => {
cleanupWorkers();
});
Loading

0 comments on commit 1e210cb

Please sign in to comment.