neo4j / neo4j-javascript-driver

Neo4j Bolt driver for JavaScript
https://neo4j.com/docs/javascript-manual/current/
Apache License 2.0
843 stars 148 forks source link

WebSocket is closed before the connection is established. #338

Closed mcpat1993 closed 6 years ago

mcpat1993 commented 6 years ago

Hello,

I'm running an Apache2 Webserver and including the driver in my index.html file as well as my Javascript that runs the queries to the Neo4j database that I have. My file heirarchy is as follows:

|--node_modules | |--VivaGraphJS | |--neo4j-driver |--index.html |--test.js The problem that I am experiencing is that the driver isn't always connecting to the database. The following "warning" is what I'm seeing: > WebSocket connection to 'ws://172.24.84.139:7687/' failed: WebSocket is closed before the connection is established. I had this issue yesterday and it somehow stopped for a while and I was able to connect to the database and and get back the data that I needed to display with VivaGraphJS. Suddenly, today I started getting it again after making a change. I undid the change and the error remained. My Chrome inspector is showing the error location being the first tag (html tag) in the index.html document. I'm not sure what is causing this issue or how to fix it. My index.html file is as follows: ```
``` My test.js file is as follows: ``` function initGraph() { var graph = Viva.Graph.graph(); //there is no authentication enabled var driver = neo4j.v1.driver("bolt://172.24.84.139:7687", neo4j.v1.auth.basic("", "")); var session = driver.session(); session .run('MATCH (p1:Object{name:"xt3lab-fabric05"}), (p2:Object), path = ((p1)-[*..5]-(p2)) RETURN path ORDER BY LENGTH(path) DESC') .then(function (result) { var nodes = [], rels = [], i = 0 result.records.forEach(function (record) { nodes.push({name: record._fields[0].end.properties.name}); graph.addLink('xt3lab-fabric05', nodes[i].name); i = i+1; }); session.close(); }) .catch(function (error) {i console.log(error); }); var graphics = Viva.Graph.View.svgGraphics(), nodeSize = 2; graphics.node(function(node) { // This time it's a group of elements: http://www.w3.org/TR/SVG/struct.html#Groups var ui = Viva.Graph.svg('g'), svgText = Viva.Graph.svg('text').attr('y', '-4px').text(node.id) ui.append(svgText); return ui; }).placeNode(function(nodeUI, pos) { // 'g' element doesn't have convenient (x,y) attributes, instead // we have to deal with transforms: http://www.w3.org/TR/SVG/coords.html#SVGGlobalTransformAttribute nodeUI.attr('transform', 'translate(' + (pos.x - nodeSize/2) + ',' + (pos.y - nodeSize/2) + ')'); }); var renderer = Viva.Graph.View.renderer(graph, { container: document.getElementById('graphContainer'), graphics : graphics }); renderer.run(); driver.close(); } ```
lutovich commented 6 years ago

Hi @mcpat1993,

I think there is a problem in the #initGraph() function. Call Session#run() is async and thus returns a promise. However, the driver instance is closed outside of the promise so it might get executed before query completes. Please see the following snippet:

...
var driver = neo4j.v1.driver("bolt://172.24.84.139:7687", neo4j.v1.auth.basic("", ""));
var session = driver.session();
session
  .run('MATCH (p1:Object{name:"xt3lab-fabric05"}), (p2:Object), path = ((p1)-[*..5]-(p2)) RETURN path ORDER BY LENGTH(path) DESC')
  .then(function (result) {
    var nodes = [], rels = [], i = 0
    result.records.forEach(function (record) {
      nodes.push({name: record._fields[0].end.properties.name});
      graph.addLink('xt3lab-fabric05', nodes[i].name);
      i = i+1;
    });
    session.close();
    driver.close(); // <<-- close driver after the whole result is consumed
  })
  .catch(function (error) {
    console.log(error);
  });
...

Hope this helps, please update this issue with the outcome.

mcpat1993 commented 6 years ago

Thanks for the quick reply, but I have added the driver.close function in the then portion of the session but I'm getting the same error. In the README file usage examples it also does not include driver.close()

lutovich commented 6 years ago

@mcpat1993 readme does mention that lifecycle of the driver needs to be explicitly managed by the application. It is not required to open/close driver per query. Recommended approach is to keep single driver per application/webpage and close it explicitly on shutdown. Relevant docs section is here.

I can only reproduce seen error when driver.close() is outside of the promise. Here is my simple code:

<script src="https://rawgit.com/neo4j/neo4j-javascript-driver/1.4/lib/browser/neo4j-web.js"></script>
<script>
  var driver = neo4j.v1.driver("bolt://localhost", neo4j.v1.auth.basic("", ""))
  var session = driver.session()
  session.run("return 42")
         .then(function(result){ console.log("SUCCESS: " + result.records[0].get(0))  })
         .catch(function(error){ console.log("ERROR: ", error)  })
         //.then(function(){ driver.close() }) // <<-- uncomment this line to fix the error

  driver.close() // <<-- comment this line to fix the error
</script>

Error:

WebSocket connection to 'ws://localhost:7687/' failed: WebSocket is closed before the connection is established.

and it never shows up when driver.close() is part of the promise chain.

Did you remove previous driver.close()? There should remain only a single one inside the promise chain.

mcpat1993 commented 6 years ago

@lutovich I think I understand what you mean. I appreciate the advice with the final .then clause of the session variable. I ended up using that. I'm ashamed at what I discovered to be my actual problem though. While my drivers URI was valid, it wasn't where my Neo4j DB was located. I must have just mistyped as it should have been 172.24.84.130 and not .139. I still think it's bizarre that I was getting that error and not a connection refused error or something like that. What a disgraceful error. Sorry to bother you, but thanks for your help.