Skip to content

Commit f3c0c6c

Browse files
authored
feat(Bigtable): add pingAndWarm Client option (#8229)
1 parent f3d645e commit f3c0c6c

2 files changed

Lines changed: 99 additions & 0 deletions

File tree

Bigtable/src/BigtableClient.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
use Google\ApiCore\ValidationException;
2626
use Google\Auth\FetchAuthTokenInterface;
2727
use Google\Cloud\Bigtable\V2\Client\BigtableClient as GapicClient;
28+
use Google\Cloud\Bigtable\V2\PingAndWarmRequest;
29+
use Google\Cloud\Core\ApiHelperTrait;
2830
use Google\Cloud\Core\DetectProjectIdTrait;
2931

3032
/**
@@ -44,6 +46,7 @@ class BigtableClient
4446
use ArrayTrait;
4547
use DetectProjectIdTrait;
4648
use ClientOptionsTrait;
49+
use ApiHelperTrait;
4750

4851
// The name of the service. Used in debug logging.
4952
private const SERVICE_NAME = 'google.bigtable.v2.Bigtable';
@@ -58,6 +61,23 @@ class BigtableClient
5861
*/
5962
private Serializer $serializer;
6063

64+
/**
65+
* Invoke {@see GapicClient::pingAndWarm()} when {@see self::table()} is called
66+
* in order to establish a persistent gRPC channel before making an RPC call.
67+
*
68+
* @experimental
69+
* @var bool
70+
*/
71+
private $pingAndWarm;
72+
73+
/**
74+
* An in-memory array to ensure pingAndWarm is only called once per instance.
75+
*
76+
* @experimental
77+
* @var array
78+
*/
79+
private $pingAndWarmCalled = [];
80+
6181
/**
6282
* Create a Bigtable client.
6383
*
@@ -109,6 +129,9 @@ class BigtableClient
109129
* supported options.
110130
* @type string $quotaProject Specifies a user project to bill for
111131
* access charges associated with the request.
132+
* @type bool $pingAndWarm EXPERIMENTAL When true, calls the
133+
* {@see GapicClient::pingAndWarm()} RPC to establish a persistent
134+
* gRPC channel before making an RPC call.
112135
* }
113136
* @throws ValidationException
114137
*/
@@ -138,6 +161,7 @@ public function __construct(array $config = [])
138161

139162
$this->projectId = $this->detectProjectId($detectProjectIdConfig);
140163
$this->serializer = new Serializer();
164+
$this->pingAndWarm = $config['pingAndWarm'] ?? false;
141165
$this->gapicClient = new GapicClient($config);
142166
}
143167

@@ -163,6 +187,17 @@ public function __construct(array $config = [])
163187
*/
164188
public function table($instanceId, $tableId, array $options = [])
165189
{
190+
if ($this->pingAndWarm && !($this->pingAndWarmCalled[$instanceId] ?? false)) {
191+
// The default deadline is configured by the "clientConfig" option, which uses
192+
// `src/V2/resources/bigtable_client_config.json`.
193+
// This default deadline should be high enough to absorb cold connection latencies.
194+
list($data, $callOptions) = $this->splitOptionalArgs($options);
195+
$data['name'] = GapicClient::instanceName($this->projectId, $instanceId);
196+
$request = $this->serializer->decodeMessage(new PingAndWarmRequest(), $data);
197+
$this->gapicClient->pingAndWarm($request, $callOptions);
198+
$this->pingAndWarmCalled[$instanceId] = true;
199+
}
200+
166201
return new Table(
167202
$this->gapicClient,
168203
$this->serializer,

Bigtable/tests/Unit/BigtableClientTest.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,23 @@
1919

2020
use Google\Cloud\Bigtable\BigtableClient;
2121
use Google\Cloud\Bigtable\Table;
22+
use Google\Cloud\Bigtable\V2\Client\BigtableClient as BigtableGapicClient;
23+
use Google\Cloud\Bigtable\V2\PingAndWarmRequest;
24+
use Google\Cloud\Bigtable\V2\PingAndWarmResponse;
2225
use Google\Cloud\Core\InsecureCredentialsWrapper;
2326
use Google\Cloud\Core\Testing\TestHelpers;
2427
use PHPUnit\Framework\TestCase;
28+
use Prophecy\Argument;
29+
use Prophecy\PhpUnit\ProphecyTrait;
2530

2631
/**
2732
* @group bigtable
2833
* @group bigtabledata
2934
*/
3035
class BigtableClientTest extends TestCase
3136
{
37+
use ProphecyTrait;
38+
3239
private $client;
3340

3441
public function setUp(): void
@@ -44,4 +51,61 @@ public function testTable()
4451

4552
$this->assertInstanceOf(Table::class, $table);
4653
}
54+
55+
public function testPingAndWarm()
56+
{
57+
$gapicClient = $this->prophesize(BigtableGapicClient::class);
58+
$gapicClient->pingAndWarm(Argument::any())
59+
->shouldNotBeCalled();
60+
61+
$bigtable = new BigtableClient([
62+
'projectId' => 'my-project',
63+
'credentials' => new InsecureCredentialsWrapper(),
64+
]);
65+
(fn() => $this->gapicClient = $gapicClient->reveal())->call($bigtable);
66+
67+
// calling "::table" without the option does not pingandwarm
68+
$bigtable->table('my-instance', 'my-table');
69+
70+
// creating the client with the option does not pingandwarm
71+
$bigtable = new BigtableClient([
72+
'projectId' => 'my-project',
73+
'credentials' => new InsecureCredentialsWrapper(),
74+
'pingAndWarm' => true, // this would throw an auth error if it was called
75+
]);
76+
77+
$pingAndWarmResponse = new PingAndWarmResponse();
78+
$gapicClient = $this->prophesize(BigtableGapicClient::class);
79+
$gapicClient->pingAndWarm(
80+
Argument::that(function (PingAndWarmRequest $request) {
81+
return $request->getName() === 'projects/my-project/instances/my-instance';
82+
}),
83+
[]
84+
)
85+
->shouldBeCalledOnce()
86+
->willReturn($pingAndWarmResponse);
87+
$gapicClient->pingAndWarm(
88+
Argument::that(function (PingAndWarmRequest $request) {
89+
return $request->getName() === 'projects/my-project/instances/my-instance-2';
90+
}),
91+
[]
92+
)
93+
->shouldBeCalledOnce()
94+
->willReturn($pingAndWarmResponse);
95+
96+
// calling "::table" with the option should call pingandwarm
97+
$bigtable = new BigtableClient([
98+
'projectId' => 'my-project',
99+
'credentials' => new InsecureCredentialsWrapper(),
100+
'gapicClient' => $gapicClient->reveal(),
101+
'pingAndWarm' => true,
102+
]);
103+
(fn() => $this->gapicClient = $gapicClient->reveal())->call($bigtable);
104+
$bigtable->table('my-instance', 'my-table');
105+
106+
// "PingAndWarm" will only be called once per instance
107+
$bigtable->table('my-instance', 'my-table'); // not called
108+
$bigtable->table('my-instance', 'my-table-2'); // still not called
109+
$bigtable->table('my-instance-2', 'my-table'); // called
110+
}
47111
}

0 commit comments

Comments
 (0)