neo4j-php / neo4j-php-client

Php client and driver for neo4j database
https://neo4j.com/developer/php/
MIT License
163 stars 40 forks source link

Parameter Array Size Limit #70

Closed in3rsha closed 3 years ago

in3rsha commented 3 years ago

I'm getting this error when trying to execute a Cypher query:

Bolt\error\ConnectException: Read error in
../vendor/stefanak-michal/bolt/src/connection/StreamSocket.php:102

What does this generally mean?

I know it's a bit vague, but I've made the same queries before, but I'm having trouble with this one for some reason, and I'm wondering where to start with debugging.

transistive commented 3 years ago

Hi @in3rsha,

Thank you for posting this issue! The read error is extremely generic. It generally happens when the StreamSocket is only able to read empty strings. Do you mind sharing your configuration?

There is a bug report template available when creating an issue. Since it is too late now, I will drop it here:

Describe the bug A clear and concise description of what the bug is.

To Reproduce Steps to reproduce the behavior:

  1. Create client with neo4j scheme
  2. Open transaction
  3. Commit transaction
  4. See error

Expected behavior A clear and concise description of what you expected to happen.

Screenshots If applicable, add screenshots to help explain your problem.

Desktop (please complete the following information):

Additional context Add any other context about the problem here.

in3rsha commented 3 years ago

Thank you. If the SteamSocket is only able to read empty strings, could this possibly be due to a problem with the Neo4j instance, such as an issue with memory?

Apologies again for not filling out the bug template. I'm asking on behalf of a friend and haven't recreated this error myself yet.

tonymullen commented 3 years ago

Hello, I've got some more details here. (Thanks @in3rsha for raising this issue for me).

I'm running this tool to ingest Bitcoin data into Neo4j: https://github.com/in3rsha/bitcoin-to-neo4j

My configuration is as follows:

Library version: versions : * 2.1.0

Neo4j Version: neo4j 4.3.3

PHP version: PHP 8.0.10

OS: Linux pop-os 5.4.0-7634-generic #38~1591219791~20.04~6b1c5de-Ubuntu SMP Thu Jun 4 02:56:10 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

The script runs as shown below, encountering the error consistently:

$ php main.php 
Reading /media/Samsung_T5/Bitcoin/blocks/blk00000.dat...

 1: 000000000af27c1a7b618ac8635b96025a5650b24c63764eca7414af6e886051 [151.50 kb] (fp:15334310) 55812
  6
   1.    80cb9856e21d0e35ff529328e8bd766a9a9bd4a10cfe2a3c099d0602b6a1eeb1 [135 bytes]     (1:1)   exists->block (+coinbase)  0.10216
   2.    0208f1f18fa2219fef618f0b3b963d13cf5ee5c2bd04d1d873146aec393563b7 [38001 bytes]   (211:1) exists->block  0.08831
   3.    30b18913d453fb34d5657ce507dbac5ad264cc5dac6fc3282a08fbda04f0897d [300 bytes]     (1:2)   exists->block  0.08355
   4.    42f4500dec4c6f8cd41337767bdf7e2caa48c153ae2114334a645ac927d03766 [112018 bytes]  (622:1) $neo->run($cypher) exception
Bolt\error\ConnectException: Read error in /home/btc-to-ne4j-fork/vendor/stefanak-michal/bolt/src/connection/StreamSocket.php:102
Stack trace:
#0 /home/btc-to-ne4j-fork/vendor/stefanak-michal/bolt/src/protocol/AProtocol.php(94): Bolt\connection\StreamSocket->read()
#1 /home/btc-to-ne4j-fork/vendor/stefanak-michal/bolt/src/protocol/V4.php(39): Bolt\protocol\AProtocol->read()
#2 /home/btc-to-ne4j-fork/vendor/stefanak-michal/bolt/src/protocol/V4.php(25): Bolt\protocol\V4->pull()
#3 /home/btc-to-ne4j-fork/vendor/stefanak-michal/bolt/src/Bolt.php(277): Bolt\protocol\V4->pullAll()
#4 /home/btc-to-ne4j-fork/vendor/laudis/neo4j-php-client/src/Bolt/BoltUnmanagedTransaction.php(124): Bolt\Bolt->pullAll()
#5 /home/btc-to-ne4j-fork/vendor/laudis/neo4j-php-client/src/Bolt/Session.php(77): Laudis\Neo4j\Bolt\BoltUnmanagedTransaction->runStatements()
#6 /home/btc-to-ne4j-fork/vendor/laudis/neo4j-php-client/src/Bolt/Session.php(87): Laudis\Neo4j\Bolt\Session->runStatements()
#7 /home/btc-to-ne4j-fork/vendor/laudis/neo4j-php-client/src/Bolt/Session.php(92): Laudis\Neo4j\Bolt\Session->runStatement()
#8 /home/btc-to-ne4j-fork/vendor/laudis/neo4j-php-client/src/Client.php(72): Laudis\Neo4j\Bolt\Session->run()
#9 /home/btc-to-ne4j-fork/cyphertx.php(216): Laudis\Neo4j\Client->run()
#10 /home/btc-to-ne4j-fork/main.php(375): cypherTx()
#11 {main}^C
in3rsha commented 3 years ago
  1. Library version: 2.1.0
  2. Neo4j Version: 4.3.3
  3. PHP version: 8.0.10
  4. OS: Ubuntu 20.04.3 LTS

I'm getting a similar error myself:

Notice: fwrite(): Send of 2 bytes failed with errno=32 Broken pipe in /stefanak-michal/bolt/src/connection/StreamSocket.php on line 88
PHP Fatal error:  Uncaught Bolt\error\ConnectException: Read error in /stefanak-michal/bolt/src/connection/StreamSocket.php:102
Stack trace:
#0 /stefanak-michal/bolt/src/protocol/AProtocol.php(94): Bolt\connection\StreamSocket->read()
#1 /stefanak-michal/bolt/src/protocol/V3.php(72): Bolt\protocol\AProtocol->read()
#2 /stefanak-michal/bolt/src/Bolt.php(262): Bolt\protocol\V3->run()
#3 /laudis/neo4j-php-client/src/Bolt/BoltUnmanagedTransaction.php(121): Bolt\Bolt->run()
#4 /laudis/neo4j-php-client/src/Bolt/Session.php(77): Laudis\Neo4j\Bolt\BoltUnmanagedTransaction->runStatements()
#5 /laudis/neo4j-php-client/src/Bolt/Session.php(87): Laudis\Neo4j\Bolt\Session->runStatements()
#6 /laudis/neo4j-php-client/src/Bolt/Session.php(92): Laudis\Neo4j\Bolt\Session->runStatement()
#7 /laudis/neo4j-php-client/src/Client.php(72): Laudis\Neo4j\Bolt\Session->run()
#8 run.php(512): Laudis\Neo4j\Client->run()
#9 {main}

This is the query that's causing the error:

$neo->run('MATCH (tx :tx {txid:$txid}) RETURN tx', $params);

I think the problem is that the $params array is about 950 bytes in size, which is larger than the previous successful queries that use the same template.

Does this mean there a limit to the size of the parameter array you can send to run()?

Note: I realize that 950 bytes of $params is unnecessary for this simple query, but I'm just using it as an example to highlight what I think is causing the error. There will be other queries that will be passed parameters of this size (and greater), and I'm just wondering if a parameter size limit is what's causing the error.

Edit: It seems the issue is not with this library but with this line here: https://github.com/neo4j-php/Bolt/blob/master/src/connection/StreamSocket.php#L88

Edit 2: It's not this specific query that's the problem. I started a fresh database and ran this same query and it accepted it without a problem. I'm starting to think this may be something to do with Neo4j 4 memory.

in3rsha commented 3 years ago

I haven't solved the problem yet, but it looks like there's a limit to the size of the parameter array you can send to run().

Here's a simple script to test:

require_once "vendor/autoload.php";

use Laudis\Neo4j\ClientBuilder;
$neo = ClientBuilder::create()
        ->withDriver('bolt', "bolt://neo4j:neo4j@127.0.0.1")
        ->withDefaultDriver('bolt')
        ->build();

// create placeholder node
$neo->run('MERGE (a:label {id:"xyz"})');

// create array of parameters
$params = [
  "id" => "xyz",
];

while (true) {
  try {

    // show current length of parameters array
    echo strlen(serialize($params)).PHP_EOL;

    // run the simple query using parameters array
    $check = $neo->run('MATCH (a :label {id:$id}) RETURN a', $params);

    // increase the size of the parameters array using random data
    $params[base64_encode(random_bytes(32))] = base64_encode(random_bytes(128));
  }
  catch (Exception $e) {
    echo $e;

    // delete placeholder node
    $neo->run('MATCH (a:label {id:"xyz"}) DELETE a');

    exit;
  }
}

For me it fails when the parameter array reaches a string length of 69006. This number varies depending on the size of the keys in the array, but it always fails at some point when the array gets too big.

Can anyone else confirm they're seeing the same error at around the 69006 mark?

Note: This error does not happen when running this same script but using the old neo4j-php-client on Neo4j 3.

in3rsha commented 3 years ago

Is this more likely to be an issue with https://github.com/neo4j-php/Bolt than this repo?

tonymullen commented 3 years ago

I can confirm that the script fails for me at roughly the same point.

transistive commented 3 years ago

Very strange behavior. We have tested a lot longer strings without a problem, but it is when creating random data the script crashes. It appears to be an issue within the bolt library. I will open an issue there to look for the problem.

Thank you for bringing this to our attention!

transistive commented 3 years ago

Fixed in version 2.1.1

Thank you all for the valuable feedback and reproducible error!

in3rsha commented 3 years ago

@transistive Thank you.

tonymullen commented 3 years ago

@transistive and @in3rsha thanks very much!