Skip to content

Commit e724777

Browse files
Merge pull request #48 from transistive/timeout-microtime
Microsecond timeout support
2 parents 20a3dda + 7c9f260 commit e724777

File tree

6 files changed

+81
-5
lines changed

6 files changed

+81
-5
lines changed

composer.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,10 @@
3636
"psr-4": {
3737
"Bolt\\": "src/"
3838
}
39+
},
40+
"autoload-dev": {
41+
"psr-4": {
42+
"Bolt\\tests\\": "tests/"
43+
}
3944
}
4045
}

src/connection/AConnection.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ abstract class AConnection implements IConnection
3131
* AConnection constructor.
3232
* @param string $ip
3333
* @param int $port
34-
* @param int $timeout
34+
* @param int|float $timeout
3535
*/
36-
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15)
36+
public function __construct(string $ip = '127.0.0.1', int $port = 7687, $timeout = 15)
3737
{
3838
$this->ip = $ip;
3939
$this->port = $port;

src/connection/IConnection.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,12 @@
1111
*/
1212
interface IConnection
1313
{
14-
public function __construct(string $ip = '127.0.0.1', int $port = 7687, int $timeout = 15);
14+
/**
15+
* @param string $ip
16+
* @param int $port
17+
* @param int|float $timeout
18+
*/
19+
public function __construct(string $ip = '127.0.0.1', int $port = 7687, $timeout = 15);
1520

1621
public function connect(): bool;
1722

src/connection/Socket.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,11 @@ public function connect(): bool
4242

4343
socket_set_option($this->socket, SOL_TCP, TCP_NODELAY, 1);
4444
socket_set_option($this->socket, SOL_SOCKET, SO_KEEPALIVE, 1);
45-
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, ['sec' => $this->timeout, 'usec' => 0]);
46-
socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, ['sec' => $this->timeout, 'usec' => 0]);
45+
$timeoutSeconds = floor($this->timeout);
46+
$microSeconds = floor(($this->timeout - $timeoutSeconds) * 1000000);
47+
$timeoutOption = ['sec' => $timeoutSeconds, 'usec' => $microSeconds];
48+
socket_set_option($this->socket, SOL_SOCKET, SO_RCVTIMEO, $timeoutOption);
49+
socket_set_option($this->socket, SOL_SOCKET, SO_SNDTIMEO, $timeoutOption);
4750

4851
$conn = @socket_connect($this->socket, $this->ip, $this->port);
4952
if (!$conn) {

src/connection/StreamSocket.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,11 @@ public function connect(): bool
6666
}
6767
}
6868

69+
$timeout = (int) floor($this->timeout);
70+
if (!stream_set_timeout($this->stream, $timeout, (int) floor(($this->timeout - $timeout) * 1000000))) {
71+
throw new ConnectException('Cannot set timeout on stream');
72+
}
73+
6974
return true;
7075
}
7176

tests/SocketTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
namespace Bolt\tests;
4+
5+
use Bolt\Bolt;
6+
use Bolt\connection\StreamSocket;
7+
use Bolt\error\ConnectException;
8+
use Exception;
9+
use PHPUnit\Framework\TestCase;
10+
11+
final class SocketTest extends TestCase
12+
{
13+
/**
14+
* @throws Exception
15+
*/
16+
public function testMillisecondTimeout(): void
17+
{
18+
$socket = new StreamSocket($GLOBALS['NEO_HOST'] ?? '127.0.0.1', (int) ($GLOBALS['NEO_PORT'] ?? 7687), 1.5);
19+
$bolt = new Bolt($socket);
20+
21+
$bolt->init('Test/1.0', $GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']);
22+
23+
$time = microtime(true);
24+
try {
25+
$bolt->run('FOREACH ( i IN range(1,10000) |
26+
MERGE (d:Day {day: i})
27+
)');
28+
} catch (ConnectException $e) {
29+
$newTime = microtime(true);
30+
31+
$this->assertEqualsWithDelta(1.5, $newTime - $time, 0.2);
32+
}
33+
34+
self::assertTrue(true);
35+
}
36+
37+
/**
38+
* @throws Exception
39+
*/
40+
public function testSecondsTimeout(): void
41+
{
42+
$socket = new StreamSocket($GLOBALS['NEO_HOST'] ?? '127.0.0.1', (int) ($GLOBALS['NEO_PORT'] ?? 7687), 1);
43+
$bolt = new Bolt($socket);
44+
$bolt->init('Test/1.0', $GLOBALS['NEO_USER'], $GLOBALS['NEO_PASS']);
45+
46+
$time = microtime(true);
47+
try {
48+
$bolt->run('FOREACH ( i IN range(1,10000) |
49+
MERGE (d:Day {day: i})
50+
)');
51+
$this->assertTrue(false, 'No timeout error triggered');
52+
} catch (ConnectException $e) {
53+
$newTime = microtime(true);
54+
55+
$this->assertEqualsWithDelta(1.0, $newTime - $time, 0.2);
56+
}
57+
}
58+
}

0 commit comments

Comments
 (0)