aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/php
diff options
context:
space:
mode:
Diffstat (limited to 'src/php')
-rw-r--r--src/php/ext/grpc/call.c1
-rw-r--r--src/php/lib/Grpc/AbstractCall.php14
-rwxr-xr-xsrc/php/lib/Grpc/BaseStub.php31
-rwxr-xr-xsrc/php/tests/interop/interop_client.php21
-rwxr-xr-xsrc/php/tests/unit_tests/TimevalTest.php22
5 files changed, 79 insertions, 10 deletions
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index 9f651ff56f..10a4946ea6 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -397,6 +397,7 @@ PHP_METHOD(Call, startBatch) {
goto cleanup;
}
ops[op_num].op = (grpc_op_type)index;
+ ops[op_num].flags = 0;
op_num++;
}
error = grpc_call_start_batch(call->wrapped, ops, op_num, call->wrapped);
diff --git a/src/php/lib/Grpc/AbstractCall.php b/src/php/lib/Grpc/AbstractCall.php
index 1add972589..5b28417a0d 100644
--- a/src/php/lib/Grpc/AbstractCall.php
+++ b/src/php/lib/Grpc/AbstractCall.php
@@ -43,9 +43,19 @@ abstract class AbstractCall {
* Create a new Call wrapper object.
* @param Channel $channel The channel to communicate on
* @param string $method The method to call on the remote server
+ * @param callback $deserialize A callback function to deserialize
+ * the response
+ * @param (optional) long $timeout Timeout in microseconds
*/
- public function __construct(Channel $channel, $method, $deserialize) {
- $this->call = new Call($channel, $method, Timeval::infFuture());
+ public function __construct(Channel $channel, $method, $deserialize, $timeout = false) {
+ if ($timeout) {
+ $now = Timeval::now();
+ $delta = new Timeval($timeout);
+ $deadline = $now->add($delta);
+ } else {
+ $deadline = Timeval::infFuture();
+ }
+ $this->call = new Call($channel, $method, $deadline);
$this->deserialize = $deserialize;
$this->metadata = null;
}
diff --git a/src/php/lib/Grpc/BaseStub.php b/src/php/lib/Grpc/BaseStub.php
index b84b6b86f8..48c00977eb 100755
--- a/src/php/lib/Grpc/BaseStub.php
+++ b/src/php/lib/Grpc/BaseStub.php
@@ -83,6 +83,21 @@ class BaseStub {
return "https://" . $this->hostname . $service_name;
}
+ /**
+ * extract $timeout from $metadata
+ * @param $metadata The metadata map
+ * @return list($metadata_copy, $timeout)
+ */
+ private function _extract_timeout_from_metadata($metadata) {
+ $timeout = false;
+ $metadata_copy = $metadata;
+ if (isset($metadata['timeout'])) {
+ $timeout = $metadata['timeout'];
+ unset($metadata_copy['timeout']);
+ }
+ return array($metadata_copy, $timeout);
+ }
+
/* This class is intended to be subclassed by generated code, so all functions
begin with "_" to avoid name collisions. */
@@ -99,8 +114,8 @@ class BaseStub {
$argument,
callable $deserialize,
$metadata = array()) {
- $call = new UnaryCall($this->channel, $method, $deserialize);
- $actual_metadata = $metadata;
+ list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata);
+ $call = new UnaryCall($this->channel, $method, $deserialize, $timeout);
$jwt_aud_uri = $this->_get_jwt_aud_uri($method);
if (is_callable($this->update_metadata)) {
$actual_metadata = call_user_func($this->update_metadata,
@@ -126,8 +141,8 @@ class BaseStub {
$arguments,
callable $deserialize,
$metadata = array()) {
- $call = new ClientStreamingCall($this->channel, $method, $deserialize);
- $actual_metadata = $metadata;
+ list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata);
+ $call = new ClientStreamingCall($this->channel, $method, $deserialize, $timeout);
$jwt_aud_uri = $this->_get_jwt_aud_uri($method);
if (is_callable($this->update_metadata)) {
$actual_metadata = call_user_func($this->update_metadata,
@@ -152,8 +167,8 @@ class BaseStub {
$argument,
callable $deserialize,
$metadata = array()) {
- $call = new ServerStreamingCall($this->channel, $method, $deserialize);
- $actual_metadata = $metadata;
+ list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata);
+ $call = new ServerStreamingCall($this->channel, $method, $deserialize, $timeout);
$jwt_aud_uri = $this->_get_jwt_aud_uri($method);
if (is_callable($this->update_metadata)) {
$actual_metadata = call_user_func($this->update_metadata,
@@ -175,8 +190,8 @@ class BaseStub {
public function _bidiRequest($method,
callable $deserialize,
$metadata = array()) {
- $call = new BidiStreamingCall($this->channel, $method, $deserialize);
- $actual_metadata = $metadata;
+ list($actual_metadata, $timeout) = $this->_extract_timeout_from_metadata($metadata);
+ $call = new BidiStreamingCall($this->channel, $method, $deserialize, $timeout);
$jwt_aud_uri = $this->_get_jwt_aud_uri($method);
if (is_callable($this->update_metadata)) {
$actual_metadata = call_user_func($this->update_metadata,
diff --git a/src/php/tests/interop/interop_client.php b/src/php/tests/interop/interop_client.php
index 9aee01cd4d..2041577557 100755
--- a/src/php/tests/interop/interop_client.php
+++ b/src/php/tests/interop/interop_client.php
@@ -270,6 +270,24 @@ function cancelAfterFirstResponse($stub) {
'Call status was not CANCELLED');
}
+function timeoutOnSleepingServer($stub) {
+ $call = $stub->FullDuplexCall(array('timeout' => 500000));
+ $request = new grpc\testing\StreamingOutputCallRequest();
+ $request->setResponseType(grpc\testing\PayloadType::COMPRESSABLE);
+ $response_parameters = new grpc\testing\ResponseParameters();
+ $response_parameters->setSize(8);
+ $request->addResponseParameters($response_parameters);
+ $payload = new grpc\testing\Payload();
+ $payload->setBody(str_repeat("\0", 9));
+ $request->setPayload($payload);
+
+ $call->write($request);
+ $response = $call->read();
+
+ hardAssert($call->getStatus()->code === Grpc\STATUS_DEADLINE_EXCEEDED,
+ 'Call status was not DEADLINE_EXCEEDED');
+}
+
$args = getopt('', array('server_host:', 'server_port:', 'test_case:',
'server_host_override:', 'oauth_scope:',
'default_service_account:'));
@@ -341,6 +359,9 @@ switch ($args['test_case']) {
case 'cancel_after_first_response':
cancelAfterFirstResponse($stub);
break;
+ case 'timeout_on_sleeping_server':
+ timeoutOnSleepingServer($stub);
+ break;
case 'service_account_creds':
serviceAccountCreds($stub, $args);
break;
diff --git a/src/php/tests/unit_tests/TimevalTest.php b/src/php/tests/unit_tests/TimevalTest.php
index a8bfcf0ac4..7b4925cad6 100755
--- a/src/php/tests/unit_tests/TimevalTest.php
+++ b/src/php/tests/unit_tests/TimevalTest.php
@@ -61,4 +61,26 @@ class TimevalTest extends PHPUnit_Framework_TestCase{
$this->assertLessThan(0, Grpc\Timeval::compare($zero, $now));
$this->assertLessThan(0, Grpc\Timeval::compare($now, $future));
}
+
+ public function testNowAndAdd() {
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(1000);
+ $deadline = $now->add($delta);
+ $this->assertGreaterThan(0, Grpc\Timeval::compare($deadline, $now));
+ }
+
+ public function testNowAndSubtract() {
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(1000);
+ $deadline = $now->subtract($delta);
+ $this->assertLessThan(0, Grpc\Timeval::compare($deadline, $now));
+ }
+
+ public function testAddAndSubtract() {
+ $now = Grpc\Timeval::now();
+ $delta = new Grpc\Timeval(1000);
+ $deadline = $now->add($delta);
+ $back_to_now = $deadline->subtract($delta);
+ $this->assertSame(0, Grpc\Timeval::compare($back_to_now, $now));
+ }
}