Skip to content

Commit 2c70b8a

Browse files
committed
Parallel, lazy, without bugs Neo4j server bootstrap
1 parent 09ba848 commit 2c70b8a

File tree

5 files changed

+87
-38
lines changed

5 files changed

+87
-38
lines changed

testing/integration-neo4j/src/test/java/com/neueda/jetbrains/plugin/graphdb/test/integration/neo4j/tests/cypher/completion/StoredProcedureCompletionTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99

1010
public class StoredProcedureCompletionTest extends BaseCompletionTest {
1111

12+
@Override
13+
public void setUp() throws Exception {
14+
super.setUp();
15+
dataSource().neo4j30();
16+
}
17+
1218
public void testContainsProceduresProcedure() throws Exception {
1319
myFixture.configureByText("test.cyp", "CALL <caret>");
1420
myFixture.completeBasic();

testing/integration-neo4j/src/test/java/com/neueda/jetbrains/plugin/graphdb/test/integration/neo4j/tests/cypher/completion/UserFunctionCompletionTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99

1010
public class UserFunctionCompletionTest extends BaseCompletionTest {
1111

12+
@Override
13+
public void setUp() throws Exception {
14+
super.setUp();
15+
dataSource().neo4j31();
16+
}
17+
1218
public void testContainsTestUserFunction() throws Exception {
1319
myFixture.configureByText("test.cyp", "RETURN testFunc<caret>");
1420
myFixture.completeBasic();

testing/integration-neo4j/src/test/java/com/neueda/jetbrains/plugin/graphdb/test/integration/neo4j/tests/cypher/util/BaseCompletionTest.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,5 @@ public abstract class BaseCompletionTest extends BaseGenericTest {
55
@Override
66
public void setUp() throws Exception {
77
super.setUp();
8-
9-
component().dataSources().refreshAllMetadata();
108
}
119
}

testing/integration-neo4j/src/test/java/com/neueda/jetbrains/plugin/graphdb/test/integration/neo4j/util/base/BaseIntegrationTest.java

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
package com.neueda.jetbrains.plugin.graphdb.test.integration.neo4j.util.base;
22

3-
import java.util.HashMap;
4-
import java.util.Map;
3+
import java.util.*;
54

5+
import com.intellij.openapi.components.ServiceManager;
66
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
77
import com.neueda.jetbrains.plugin.graphdb.database.neo4j.bolt.Neo4jBoltConfiguration;
88
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.DataSourceType;
99
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.DataSourcesComponent;
1010
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.metadata.DataSourcesComponentMetadata;
1111
import com.neueda.jetbrains.plugin.graphdb.jetbrains.component.datasource.state.DataSourceApi;
12+
import com.neueda.jetbrains.plugin.graphdb.language.cypher.completion.metadata.CypherMetadataProviderService;
1213
import com.neueda.jetbrains.plugin.graphdb.test.database.neo4j.common.Neo4jServer;
1314
import com.neueda.jetbrains.plugin.graphdb.test.integration.neo4j.util.server.Neo4j30ServerLoader;
1415
import com.neueda.jetbrains.plugin.graphdb.test.integration.neo4j.util.server.Neo4j31ServerLoader;
@@ -20,31 +21,23 @@ public abstract class BaseIntegrationTest extends LightCodeInsightFixtureTestCas
2021

2122
private Components components;
2223
private DataSources dataSources;
23-
private DataSourceApi neo4j30DataSource;
24-
private DataSourceApi neo4j31DataSource;
24+
private Services services;
2525

2626
@Override
2727
public void setUp() throws Exception {
2828
super.setUp();
2929
components = new Components();
3030
dataSources = new DataSources();
31+
services = new Services();
3132

32-
neo4j30DataSource = component().dataSources()
33-
.getDataSourceContainer()
34-
.getDataSource(NEO4J30)
35-
.orElseGet(() -> {
36-
DataSourceApi dataSource = createDataSource(NEO4J30, Neo4j30ServerLoader.getInstance());
37-
component().dataSources().getDataSourceContainer().addDataSource(dataSource);
38-
return dataSource;
39-
});
40-
neo4j31DataSource = component().dataSources()
41-
.getDataSourceContainer()
42-
.getDataSource(NEO4J31)
43-
.orElseGet(() -> {
44-
DataSourceApi dataSource = createDataSource(NEO4J31, Neo4j31ServerLoader.getInstance());
45-
component().dataSources().getDataSourceContainer().addDataSource(dataSource);
46-
return dataSource;
47-
});
33+
// Clean up any data sources & their information
34+
List<DataSourceApi> dataSources = new ArrayList<>(component().dataSources().getDataSourceContainer().getDataSources());
35+
component().dataSources().getDataSourceContainer().removeDataSources(dataSources);
36+
dataSources.forEach(dataSource -> services().cypherMetadataProvider().wipeContainer(dataSource.getName()));
37+
}
38+
39+
public Services services() {
40+
return services;
4841
}
4942

5043
public Components component() {
@@ -70,6 +63,12 @@ private DataSourceApi createDataSource(String name, Neo4jServer neo4jServer) {
7063
);
7164
}
7265

66+
public final class Services {
67+
public CypherMetadataProviderService cypherMetadataProvider() {
68+
return ServiceManager.getService(getProject(), CypherMetadataProviderService.class);
69+
}
70+
}
71+
7372
public final class Components {
7473
public DataSourcesComponent dataSources() {
7574
return getProject().getComponent(DataSourcesComponent.class);
@@ -80,12 +79,41 @@ public DataSourcesComponentMetadata dataSourcesMetadata() {
8079
}
8180
}
8281

82+
/**
83+
* Lazily bootstrap Neo4j server and create data sources.
84+
* Some tests might even don't need running Neo4j server!
85+
*/
8386
public final class DataSources {
87+
private DataSourceApi neo4j30DataSource;
88+
private DataSourceApi neo4j31DataSource;
89+
8490
public DataSourceApi neo4j30() {
91+
if (neo4j30DataSource == null) {
92+
neo4j30DataSource = component().dataSources()
93+
.getDataSourceContainer()
94+
.getDataSource(NEO4J30)
95+
.orElseGet(() -> {
96+
DataSourceApi dataSource = createDataSource(NEO4J30, Neo4j30ServerLoader.getInstance());
97+
component().dataSources().getDataSourceContainer().addDataSource(dataSource);
98+
component().dataSources().refreshAllMetadata();
99+
return dataSource;
100+
});
101+
}
85102
return neo4j30DataSource;
86103
}
87104

88105
public DataSourceApi neo4j31() {
106+
if (neo4j31DataSource == null) {
107+
neo4j31DataSource = component().dataSources()
108+
.getDataSourceContainer()
109+
.getDataSource(NEO4J31)
110+
.orElseGet(() -> {
111+
DataSourceApi dataSource = createDataSource(NEO4J31, Neo4j31ServerLoader.getInstance());
112+
component().dataSources().getDataSourceContainer().addDataSource(dataSource);
113+
component().dataSources().refreshAllMetadata();
114+
return dataSource;
115+
});
116+
}
89117
return neo4j31DataSource;
90118
}
91119
}

testing/integration-neo4j/src/test/java/com/neueda/jetbrains/plugin/graphdb/test/integration/neo4j/util/server/Neo4jServerLoader.java

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
public abstract class Neo4jServerLoader implements Neo4jServer {
1919

2020
private final ExecutorService executor;
21+
private Future<Neo4jServer> neo4jServerFuture;
2122
private Neo4jServer neo4jServer;
2223

2324
public Neo4jServerLoader() {
@@ -30,7 +31,7 @@ public Neo4jServerLoader() {
3031

3132
@Override
3233
public void start() {
33-
Future<Neo4jServer> future = executor.submit(() -> {
34+
neo4jServerFuture = executor.submit(() -> {
3435
try {
3536
// Initialize class loader
3637
JarClassLoader jarClassLoader = new JarClassLoader();
@@ -46,43 +47,53 @@ public void start() {
4647
// Start Neo4j server in separate thread
4748
Neo4jServer neo4jServer = (Neo4jServer) factory.create(jarClassLoader, getNeo4jServerClass());
4849
neo4jServer.start();
50+
4951
return neo4jServer;
5052
} catch (Exception e) {
5153
e.printStackTrace();
5254
return null;
5355
}
5456
});
55-
try {
56-
neo4jServer = future.get();
57-
} catch (Exception e) {
58-
Throwables.propagate(e);
59-
}
60-
if (neo4jServer == null) {
61-
throw new IllegalStateException("Neo4j server should not be null");
62-
}
63-
64-
cleanupNeo4jKnownHosts();
6557
}
6658

6759
@Override
6860
public String getBoltHost() {
69-
return neo4jServer.getBoltHost();
61+
return getNeo4jServer().getBoltHost();
7062
}
7163

7264
@Override
7365
public String getBoltPort() {
74-
return neo4jServer.getBoltPort();
66+
return getNeo4jServer().getBoltPort();
67+
}
68+
69+
private synchronized Neo4jServer getNeo4jServer() {
70+
if (neo4jServer == null) {
71+
try {
72+
neo4jServer = neo4jServerFuture.get();
73+
} catch (Exception e) {
74+
Throwables.propagate(e);
75+
}
76+
if (neo4jServer == null) {
77+
throw new IllegalStateException("Neo4j server should not be null");
78+
}
79+
80+
cleanupNeo4jKnownHosts(this);
81+
return neo4jServer;
82+
}
83+
84+
return neo4jServer;
7585
}
7686

77-
private void cleanupNeo4jKnownHosts() {
87+
private static synchronized void cleanupNeo4jKnownHosts(Neo4jServerLoader neo4jServerLoader) {
7888
File hostsFile = Config.defaultConfig().trustStrategy().certFile();
7989
try {
8090
if (hostsFile.isFile()) {
8191
List<String> lines = FileUtil.loadLines(hostsFile);
8292
List<String> updatedLines = lines.stream()
83-
.filter((line) -> !line.startsWith(getBoltHost() + ":" + getBoltPort()))
93+
.filter((line) -> !line.startsWith(neo4jServerLoader.getBoltHost() + ":" + neo4jServerLoader.getBoltPort()))
94+
.filter((line) -> !line.isEmpty())
8495
.collect(Collectors.toList());
85-
FileUtil.writeToFile(hostsFile, String.join(System.lineSeparator(), updatedLines));
96+
FileUtil.writeToFile(hostsFile, String.join(System.lineSeparator(), updatedLines) + System.lineSeparator());
8697
}
8798
} catch (Exception e) {
8899
Throwables.propagate(e);

0 commit comments

Comments
 (0)