Skip to content

Conversation

@dwsupplee
Copy link
Contributor

@dwsupplee dwsupplee commented Apr 7, 2017

Introducing.... Google Cloud Spanner support for PHP!

This PR is ready for review and feedback with a small caveat, there are a small handful of tests which need to be updated yet.

A few items worth noting for discussion:

  • A request from the Spanner team for the session pool was to prime transactions - we have left this out of our current cache based session pool implementation. For every transaction we expend we would need to immediately replace it with a fresh one - given that the pool is managed by each request flowing through the code this wouldn't provide any optimizations unfortunately. Ideally, in time, we will add other session pool implementations that can run as a process alongside the application code and gain the benefits of priming the transactions.
  • The cache based session pool relies on a locking mechanism in order to prevent concurrent requests from colliding. Symfony just recently introduced a lock component which covers the use cases we were already attempting to implement. As locking can can be complex, it seems sensible to use a component which has had lots of eyes on it and serious consideration taken into it's design and testing. The downside here, is that the component requires PHP > 5.5.9 (where we currently require > 5.5) and it will not be officially released until May. I am okay with bumping our required version of PHP up slightly, as it is highly unlikely any users are running versions between 5.5 and 5.5.9.. Thoughts are certainly appreciated, however. - Update The symfony lock component has been postponed to Symfony 3.4. As is such, it is no longer safe to rely on it being available. We will be using a dev-master commit from the symfony lock component during the early stages of alpha with plans to transition to our own locking mechanisms soon thereafter.

/cc @vkedia @tmatsuo

https://github.com/dwsupplee/gcloud-php/tree/spanner/src/Spanner

TODO

  • Remove $options.transaction from Database::runTransaction(). (jdp)
  • Support single-use transactions in Database::transaction(), runTransaction(). (jdp)
  • Make Database mutation methods use abort retry. (jdp)
  • Add static method to Date to create with year, month, day
  • Fix labels on updateInstance (possible race condition) (jdp)
  • Buffer rows in Result until resumeToken is received (dws)
  • P1 system test coverage to spec. (both)

@dwsupplee dwsupplee added the api: spanner Issues related to the Spanner API. label Apr 7, 2017
@googlebot googlebot added the cla: no This human has *not* signed the Contributor License Agreement. label Apr 7, 2017
@dwsupplee dwsupplee added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Apr 7, 2017
@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Apr 7, 2017
@dwsupplee dwsupplee added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Apr 7, 2017
Copy link
Contributor

@jdpedrie jdpedrie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

couple odds and ends. still need to take more time studying the pool implementation.

* }
*/
public function __construct(array $customFilters = [])
public function __construct(array $config = [])

This comment was marked as spam.

'outputVersionFormat' => function ($v) {
return self::$versionFormatMap[$v];
}
'customFilters' => [

This comment was marked as spam.

$this->codec = new PhpArray(['publishTime' => function ($v) {
return $this->formatTimestampFromApi($v);
}]);
$this->codec = new PhpArray([

This comment was marked as spam.

public function __construct(array $config = [])
{
$this->codec = new PhpArray([
'customFilters' => [

This comment was marked as spam.

@vkedia
Copy link

vkedia commented Apr 7, 2017

Thanks for sending this. Really excited to see this!!
I am out of office till 15th. I will take a look after that.

@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Apr 10, 2017
@jdpedrie jdpedrie added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Apr 10, 2017
@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Apr 10, 2017
@jdpedrie jdpedrie added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Apr 10, 2017
@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Apr 10, 2017
@jdpedrie jdpedrie added cla: yes This human has signed the Contributor License Agreement. and removed cla: no This human has *not* signed the Contributor License Agreement. labels Apr 10, 2017
@tmatsuo
Copy link
Contributor

tmatsuo commented Apr 11, 2017

@dwsupplee Thanks!
I don't see any major issues requiring 5.5.9

* @var array
*/
private static $defaultConfig = [
'maxSessions' => PHP_INT_MAX,

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

{
$sessions = [];

for ($i = 0; $i < $count; $i++) {

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Copy link

@vkedia vkedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made some headway into the review.

@@ -0,0 +1,44 @@
{
"title": "Spanner",

This comment was marked as spam.

This comment was marked as spam.

return false;
});

$delay = $metadata[0]['retryDelay'];

This comment was marked as spam.

});

$delay = $metadata[0]['retryDelay'];
if (!isset($delay['seconds'])) {

This comment was marked as spam.

This comment was marked as spam.

* @param array $options [optional] Configuration options.
* @return mixed|null
*/
public function result(array $options = [])

This comment was marked as spam.

This comment was marked as spam.

* @see https://cloud.google.com/spanner/docs/reference/rpc/google.spanner.admin.instance.v1#instanceconfig InstanceConfig
* @codingStandardsIgnoreEnd
*/
class Configuration

This comment was marked as spam.

}

/**
* Create and return a new read/write Transaction.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

* @param array $options [optional] Configuration options.
* @return Timestamp The commit Timestamp.
*/
public function insertBatch($table, array $dataSet, array $options = [])

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

/**
* Update a row.
*
* Only data which you wish to update need be included. You must provide

This comment was marked as spam.

This comment was marked as spam.

} finally {
$session->setExpiration();
}
}

This comment was marked as spam.

} finally {
$session->setExpiration();
}
}

This comment was marked as spam.

@googlebot googlebot added cla: no This human has *not* signed the Contributor License Agreement. and removed cla: yes This human has signed the Contributor License Agreement. labels Apr 18, 2017
@vkedia
Copy link

vkedia commented May 4, 2017

Also do you guys handle null values everywhere? So params can be null (in that case how do you infer the type of the param?). Column values can be null, arrays can contain null.

@jdpedrie
Copy link
Contributor

jdpedrie commented May 4, 2017

@vkedia, I'm looking into that now.

What is a column definition which would accept null values as array elements?

Column definition:

arrayField ARRAY<INT64> NOT NULL

Insert data:

$database->insert('tableName', [
    'arrayField' => [1, 2, null]
]);

Error:

FailedPreconditionException: Invalid value for column arrayField in table tableName: Expected INT64

That error isn't surprising, but I can't think of how one would add a null array element. The documentation says it is possible.

@vkedia
Copy link

vkedia commented May 5, 2017

@jdpedrie I believe all arrays can contain null elements. Can you try removing "NOT NULL" from there?

@jdpedrie
Copy link
Contributor

jdpedrie commented May 5, 2017

@vkedia that did the trick. sorry for the noise.

@vkedia
Copy link

vkedia commented May 5, 2017

@jdpedrie Actually I am surprised that specifying "NOT NULL" also makes the elements be non nullable.

@dwsupplee
Copy link
Contributor Author

@vkedia is there anything else we need to touch on besides #438 (comment)?

'maxSessions' => PHP_INT_MAX,
'minSessions' => 1,
'shouldWaitForSession' => true,
'maxCyclesToWaitForSession' => 30,

This comment was marked as spam.

This comment was marked as spam.

* @var array
*/
private static $defaultConfig = [
'maxSessions' => PHP_INT_MAX,

This comment was marked as spam.

{
$sessions = [];

for ($i = 0; $i < $count; $i++) {

This comment was marked as spam.

{
foreach ($data['inUse'] as $key => $session) {
if ($session['lastActive'] + 1200 < $this->time()) {
unset($data['inUse'][$key]);

This comment was marked as spam.

This comment was marked as spam.

$session = array_shift($data['queue']);

if ($session) {
if ($session['expiration'] - 60 < $this->time()) {

This comment was marked as spam.

This comment was marked as spam.

*/
private function purgeOrphanedToCreateItems(array &$data)
{
foreach ($data['toCreate'] as $key => $timestamp) {

This comment was marked as spam.

This comment was marked as spam.

* @param array $config [optional] {
* Configuration Options.
*
* @type int $maxSessions The maximum number of sessions to store in the

This comment was marked as spam.

public function release(Session $session);

/**
* Clear the session pool.

This comment was marked as spam.

@vkedia
Copy link

vkedia commented May 9, 2017

I have added a bunch of comments to the SessionPool.

@dwsupplee
Copy link
Contributor Author

Thanks for all the notes @vkedia! It's greatly appreciated.

jdpedrie and others added 6 commits May 15, 2017 18:13
Add system test coverage.

Add more read system tests and fix KeyRange issues

Spanner transaction system tests

Add remaining p0 spanner system tests
doc fix

address code review

move symfony/lock from require to suggest
},
"suggest": {
"google/gax": "Required to support gRPC",
"google/proto-client-php": "Required to support gRPC"

This comment was marked as spam.

Copy link

@vkedia vkedia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couple of minor comments

* on an interval that matches when you expect to see a decrease in traffic.
* This will help ensure you never run into issues where the Spanner backend is
* locked up after having met the maximum number of sessions assigned per node
* (The current maximum sessions per node is 10k).

This comment was marked as spam.

This comment was marked as spam.


return [
'deleted' => count($toDelete) - count($failed),
'failed' => $failed

This comment was marked as spam.

This comment was marked as spam.

/**
* Insert a row.
*
* Mutations are committed in a single-use transaction.

This comment was marked as spam.

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api: spanner Issues related to the Spanner API. cla: no This human has *not* signed the Contributor License Agreement.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants