Skip to content

Commit

Permalink
Ensure server automatically reconnects when connection is lost (#111)
Browse files Browse the repository at this point in the history
* properly reconnects when connection is lost

* avoid using node js type directly
  • Loading branch information
OskarDamkjaer authored Oct 16, 2023
1 parent 3d11353 commit 6bef223
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 18 deletions.
2 changes: 1 addition & 1 deletion packages/neo4j-schema-poller/src/neo4j-connection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Neo4jConnection {

async healthcheck() {
try {
await this.driver.verifyConnectivity();
await this.driver.verifyConnectivity({ database: this.currentDb });
return true;
} catch (error) {
return false;
Expand Down
34 changes: 34 additions & 0 deletions packages/neo4j-schema-poller/src/neo4j-schema-poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { listDatabases } from './queries/databases.js';
export class Neo4jSchemaPoller {
public connection?: Neo4jConnection;
public metadata?: MetadataPoller;
private reconnectionTimeout?: ReturnType<typeof setTimeout>;

async connect(
url: string,
Expand Down Expand Up @@ -47,10 +48,43 @@ export class Neo4jSchemaPoller {
this.metadata.startBackgroundPolling();
}

async persistentConnect(
url: string,
credentials: { username: string; password: string },
config: { driverConfig?: Config; appName: string },
) {
const shouldHaveConnection = this.connection !== undefined;
const connectionAlive = await this.connection?.healthcheck();

if (!connectionAlive) {
if (shouldHaveConnection) {
console.error('Connection to Neo4j dropped');
this.disconnect();
}

try {
await this.connect(url, credentials, config);
// eslint-disable-next-line no-console
console.log('Established connection to Neo4j');
} catch (error) {
console.error(
`Unable to connect to Neo4j: ${String(
error,
)}. Retrying in 30 seconds.`,
);
}
}

this.reconnectionTimeout = setTimeout(() => {
void this.persistentConnect(url, credentials, config);
}, 30000);
}

disconnect() {
this.connection?.dispose();
this.metadata?.stopBackgroundPolling();
this.connection = undefined;
this.metadata = undefined;
clearTimeout(this.reconnectionTimeout);
}
}
28 changes: 11 additions & 17 deletions packages/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,30 +95,24 @@ connection.onCompletion(doAutoCompletion(documents, neo4jSdk));

connection.onDidChangeConfiguration(
(params: { settings: { cypherLSP: CypherLSPSettings } }) => {
const neo4jConfig = params.settings.cypherLSP.neo4j;

neo4jSdk.disconnect();

const neo4jConfig = params.settings.cypherLSP.neo4j;
if (
neo4jSdk.connection === undefined &&
neo4jConfig.connect &&
neo4jConfig.password &&
neo4jConfig.URL &&
neo4jConfig.user
) {
neo4jSdk
.connect(
neo4jConfig.URL,
{
username: neo4jConfig.user,
password: neo4jConfig.password,
},
{ appName: 'cypher-language-server' },
)
.then(() => {
neo4jSdk.metadata.startBackgroundPolling();
})
.catch((error) => {
console.error(`Unable to connect to Neo4j: ${String(error)}`);
});
void neo4jSdk.persistentConnect(
neo4jConfig.URL,
{
username: neo4jConfig.user,
password: neo4jConfig.password,
},
{ appName: 'cypher-language-server' },
);
}
},
);
Expand Down

0 comments on commit 6bef223

Please sign in to comment.